Hans Leidekker : webservices: Don' t read past the closing bracket in read_element.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Mar 2 11:26:10 CST 2016


Module: wine
Branch: master
Commit: b7178446fc123d1b25ed72a8c235a90dfd38f943
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b7178446fc123d1b25ed72a8c235a90dfd38f943

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Mar  2 14:06:25 2016 +0100

webservices: Don't read past the closing bracket in read_element.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c              | 125 ++++++++++++++++++---------------
 dlls/webservices/tests/reader.c        |   4 +-
 dlls/webservices/webservices_private.h |   2 -
 dlls/webservices/writer.c              |  11 ++-
 4 files changed, 79 insertions(+), 63 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 37c2045..db68733 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -1001,11 +1001,47 @@ error:
     return hr;
 }
 
+static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
+{
+    ULONG i;
+    if (len1 != len2) return 1;
+    for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
+    return 0;
+}
+
+static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING *prefix,
+                                      const WS_XML_STRING *localname )
+{
+    struct node *parent;
+    const WS_XML_STRING *str;
+
+    for (parent = reader->current; parent; parent = parent->parent)
+    {
+        if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_BOF)
+        {
+            if (!localname) return parent;
+            return NULL;
+        }
+        else if (parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT)
+        {
+            if (!localname) return parent;
+
+            str = parent->hdr.prefix;
+            if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
+            str = parent->hdr.localName;
+            if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
+            return parent;
+       }
+    }
+
+    return NULL;
+}
+
 static HRESULT read_element( struct reader *reader )
 {
     unsigned int len = 0, ch, skip;
     const unsigned char *start;
-    struct node *node;
+    struct node *node = NULL, *parent;
     WS_XML_ELEMENT_NODE *elem;
     WS_XML_ATTRIBUTE *attr;
     HRESULT hr = WS_E_INVALID_FORMAT;
@@ -1018,9 +1054,6 @@ static HRESULT read_element( struct reader *reader )
         return S_OK;
     }
 
-    if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) return E_OUTOFMEMORY;
-    elem = (WS_XML_ELEMENT_NODE *)node;
-
     if (read_cmp( reader, "<", 1 )) goto error;
     read_skip( reader, 1 );
 
@@ -1034,6 +1067,12 @@ static HRESULT read_element( struct reader *reader )
     }
     if (!len) goto error;
 
+    if (!(parent = read_find_parent( reader, NULL, NULL ))) goto error;
+
+    hr = E_OUTOFMEMORY;
+    if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
+    elem = (WS_XML_ELEMENT_NODE *)node;
+
     if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
     hr = E_OUTOFMEMORY;
     if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
@@ -1053,26 +1092,8 @@ static HRESULT read_element( struct reader *reader )
         reader->current_attr++;
     }
 
-    read_skip_whitespace( reader );
-    if (read_cmp( reader, ">", 1 ) && read_cmp( reader, "/>", 2 ))
-    {
-        hr = WS_E_INVALID_FORMAT;
-        goto error;
-    }
-
-    read_insert_node( reader, reader->current, node );
-    if (!read_cmp( reader, "/>", 2 ))
-    {
-        read_skip( reader, 2 );
-        if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
-        read_insert_node( reader, reader->current, node );
-        reader->state = READER_STATE_ENDELEMENT;
-    }
-    else
-    {
-        read_skip( reader, 1 );
-        reader->state = READER_STATE_STARTELEMENT;
-    }
+    read_insert_node( reader, parent, node );
+    reader->state = READER_STATE_STARTELEMENT;
     return S_OK;
 
 error:
@@ -1112,10 +1133,27 @@ static HRESULT read_text( struct reader *reader )
     return S_OK;
 }
 
+static HRESULT read_node( struct reader * );
+
 static HRESULT read_startelement( struct reader *reader )
 {
-    if (!read_cmp( reader, "<", 1 )) return read_element( reader );
-    return read_text( reader );
+    struct node *node;
+
+    read_skip_whitespace( reader );
+    if (!read_cmp( reader, "/>", 2 ))
+    {
+        read_skip( reader, 2 );
+        if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
+        read_insert_node( reader, reader->current, node );
+        reader->state = READER_STATE_ENDELEMENT;
+        return S_OK;
+    }
+    else if (!read_cmp( reader, ">", 1 ))
+    {
+        read_skip( reader, 1 );
+        return read_node( reader );
+    }
+    return WS_E_INVALID_FORMAT;
 }
 
 static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
@@ -1148,36 +1186,6 @@ static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
     return hr;
 }
 
-static int cmp_name( const unsigned char *name1, ULONG len1, const unsigned char *name2, ULONG len2 )
-{
-    ULONG i;
-    if (len1 != len2) return 1;
-    for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return 1; }
-    return 0;
-}
-
-struct node *find_parent_element( struct node *node, const WS_XML_STRING *prefix,
-                                  const WS_XML_STRING *localname )
-{
-    struct node *parent;
-    const WS_XML_STRING *str;
-
-    for (parent = node; parent; parent = parent->parent)
-    {
-        if (parent->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) continue;
-        if (!localname) return parent;
-
-        str = parent->hdr.prefix;
-        if (cmp_name( str->bytes, str->length, prefix->bytes, prefix->length )) continue;
-
-        str = parent->hdr.localName;
-        if (cmp_name( str->bytes, str->length, localname->bytes, localname->length )) continue;
-
-        return parent;
-    }
-    return NULL;
-}
-
 static HRESULT read_endelement( struct reader *reader )
 {
     struct node *node, *parent;
@@ -1204,7 +1212,7 @@ static HRESULT read_endelement( struct reader *reader )
     }
 
     if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
-    parent = find_parent_element( reader->current, prefix, localname );
+    parent = read_find_parent( reader, prefix, localname );
     heap_free( prefix );
     heap_free( localname );
     if (!parent) return WS_E_INVALID_FORMAT;
@@ -1333,7 +1341,8 @@ static HRESULT read_node( struct reader *reader )
         else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
         else if (!read_cmp( reader, "<![CDATA[", 9 )) return read_startcdata( reader );
         else if (!read_cmp( reader, "<!--", 4 )) return read_comment( reader );
-        else if (!read_cmp( reader, "<", 1 )) return read_startelement( reader );
+        else if (!read_cmp( reader, "<", 1 )) return read_element( reader );
+        else if (!read_cmp( reader, "/>", 2 ) || !read_cmp( reader, ">", 1 )) return read_startelement( reader );
         else return read_text( reader );
     }
 }
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 720379e..62a8846 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -2045,7 +2045,7 @@ static void test_WsGetNamespaceFromPrefix(void)
     hr = set_input( reader, "<prefix:t xmlns:prefix2='ns'/>", sizeof("<prefix:t xmlns:prefix2='ns'/>") - 1 );
     ok( hr == S_OK, "got %08x\n", hr );
     hr = WsReadStartElement( reader, NULL );
-    todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+    ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
 
     prepare_namespace_test( reader, "<t></t>" );
     ns = NULL;
@@ -2132,7 +2132,7 @@ static void test_WsGetNamespaceFromPrefix(void)
 
     prepare_namespace_test( reader, "<t xmlns:prefix='ns'></t>" );
     hr = WsReadStartElement( reader, NULL );
-    todo_wine ok( hr == S_OK, "got %08x\n", hr );
+    ok( hr == S_OK, "got %08x\n", hr );
     hr = WsReadEndElement( reader, NULL );
     todo_wine ok( hr == S_OK, "got %08x\n", hr );
     hr = WsGetNamespaceFromPrefix( reader, &prefix, TRUE, &ns, NULL );
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index 4eeedf5..bae2149 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -32,8 +32,6 @@ WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
 WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
 HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
 void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
-struct node *find_parent_element( struct node *, const WS_XML_STRING *,
-                                  const WS_XML_STRING * ) DECLSPEC_HIDDEN;
 
 struct node
 {
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 14bddfb..f29b257 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -597,9 +597,18 @@ static HRESULT write_startelement( struct writer *writer )
     return S_OK;
 }
 
+static struct node *write_find_parent_element( struct writer *writer )
+{
+    struct node *node = writer->current;
+
+    if (node->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT) return node;
+    if (node->parent->hdr.node.nodeType == WS_XML_NODE_TYPE_ELEMENT) return node->parent;
+    return NULL;
+}
+
 static HRESULT write_endelement( struct writer *writer )
 {
-    struct node *node = find_parent_element( writer->current, NULL, NULL );
+    struct node *node = write_find_parent_element( writer );
     WS_XML_ELEMENT_NODE *elem = &node->hdr;
     ULONG size;
     HRESULT hr;




More information about the wine-cvs mailing list