@@ -98,6 +98,13 @@ static encodePtr get_create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlCh
98
98
return enc ;
99
99
}
100
100
101
+ /* Necessary for some error paths to avoid leaking persistent memory. */
102
+ static void requestify_string (xmlChar * * str ) {
103
+ xmlChar * copy = (xmlChar * ) estrdup ((const char * ) * str );
104
+ xmlFree (* str );
105
+ * str = copy ;
106
+ }
107
+
101
108
static void schema_load_file (sdlCtx * ctx , xmlAttrPtr ns , xmlChar * location , xmlAttrPtr tns , int import ) {
102
109
if (location != NULL &&
103
110
!zend_hash_str_exists (& ctx -> docs , (char * )location , xmlStrlen (location ))) {
@@ -110,22 +117,35 @@ static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlA
110
117
sdl_restore_uri_credentials (ctx );
111
118
112
119
if (doc == NULL ) {
120
+ requestify_string (& location );
113
121
soap_error1 (E_ERROR , "Parsing Schema: can't import schema from '%s'" , location );
114
122
}
115
123
schema = get_node (doc -> children , "schema" );
116
124
if (schema == NULL ) {
125
+ requestify_string (& location );
117
126
xmlFreeDoc (doc );
118
127
soap_error1 (E_ERROR , "Parsing Schema: can't import schema from '%s'" , location );
119
128
}
120
129
new_tns = get_attribute (schema -> properties , "targetNamespace" );
121
130
if (import ) {
122
131
if (ns != NULL && (new_tns == NULL || xmlStrcmp (ns -> children -> content , new_tns -> children -> content ) != 0 )) {
123
- xmlFreeDoc (doc );
124
- soap_error2 (E_ERROR , "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'" , location , ns -> children -> content );
132
+ requestify_string (& location );
133
+ if (new_tns == NULL ) {
134
+ xmlFreeDoc (doc );
135
+ soap_error2 (E_ERROR , "Parsing Schema: can't import schema from '%s', missing 'targetNamespace', expected '%s'" , location , ns -> children -> content );
136
+ } else {
137
+ /* Have to make a copy to avoid a UAF after freeing `doc` */
138
+ const char * target_ns_copy = estrdup ((const char * ) new_tns -> children -> content );
139
+ xmlFreeDoc (doc );
140
+ soap_error3 (E_ERROR , "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s', expected '%s'" , location , target_ns_copy , ns -> children -> content );
141
+ }
125
142
}
126
143
if (ns == NULL && new_tns != NULL ) {
144
+ requestify_string (& location );
145
+ /* Have to make a copy to avoid a UAF after freeing `doc` */
146
+ const char * target_ns_copy = estrdup ((const char * ) new_tns -> children -> content );
127
147
xmlFreeDoc (doc );
128
- soap_error2 (E_ERROR , "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s'" , location , new_tns -> children -> content );
148
+ soap_error2 (E_ERROR , "Parsing Schema: can't import schema from '%s', unexpected 'targetNamespace'='%s', expected no 'targetNamespace' " , location , target_ns_copy );
129
149
}
130
150
} else {
131
151
new_tns = get_attribute (schema -> properties , "targetNamespace" );
@@ -134,6 +154,7 @@ static void schema_load_file(sdlCtx *ctx, xmlAttrPtr ns, xmlChar *location, xmlA
134
154
xmlSetProp (schema , BAD_CAST ("targetNamespace" ), tns -> children -> content );
135
155
}
136
156
} else if (tns != NULL && xmlStrcmp (tns -> children -> content , new_tns -> children -> content ) != 0 ) {
157
+ requestify_string (& location );
137
158
xmlFreeDoc (doc );
138
159
soap_error1 (E_ERROR , "Parsing Schema: can't include schema from '%s', different 'targetNamespace'" , location );
139
160
}
0 commit comments