[PATCH v3 1/3] webservices: Respect session dictionary size limits on send dictionary.

Hans Leidekker hans at codeweavers.com
Thu Apr 21 05:04:50 CDT 2022


From: Connor McAdams <cmcadams at codeweavers.com>

v3: Warn when maximum size is reached.

Signed-off-by: Connor McAdams <cmcadams at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/channel.c             | 21 +++++++++++++++------
 dlls/webservices/string.c              |  5 ++++-
 dlls/webservices/webservices_private.h |  4 +++-
 3 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c
index 4941844afe5..7dd78335e11 100644
--- a/dlls/webservices/channel.c
+++ b/dlls/webservices/channel.c
@@ -327,8 +327,8 @@ static void reset_channel( struct channel *channel )
     channel->state         = WS_CHANNEL_STATE_CREATED;
     channel->session_state = SESSION_STATE_UNINITIALIZED;
     clear_addr( &channel->addr );
-    clear_dict( &channel->dict_send );
-    clear_dict( &channel->dict_recv );
+    init_dict( &channel->dict_send, channel->dict_size );
+    init_dict( &channel->dict_recv, 0 );
     channel->msg           = NULL;
     channel->read_size     = 0;
     channel->send_size     = 0;
@@ -485,6 +485,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding,
         channel->u.tcp.socket = -1;
         channel->encoding     = WS_ENCODING_XML_BINARY_SESSION_1;
         channel->dict_size    = 2048;
+        channel->dict_send.str_bytes_max = channel->dict_size;
         break;
 
     case WS_UDP_CHANNEL_BINDING:
@@ -544,6 +545,7 @@ static HRESULT create_channel( WS_CHANNEL_TYPE type, WS_CHANNEL_BINDING binding,
             }
 
             channel->dict_size = *(ULONG *)prop->value;
+            channel->dict_send.str_bytes_max = channel->dict_size;
             break;
 
         default:
@@ -1615,6 +1617,13 @@ static HRESULT CALLBACK dict_cb( void *state, const WS_XML_STRING *str, BOOL *fo
         return S_OK;
     }
 
+    if (str->length + dict->str_bytes + 1 > dict->str_bytes_max)
+    {
+        WARN( "max string bytes exceeded\n" );
+        *found = FALSE;
+        return hr;
+    }
+
     if (!(bytes = malloc( str->length ))) return E_OUTOFMEMORY;
     memcpy( bytes, str->bytes, str->length );
     if ((hr = insert_string( dict, bytes, str->length, index, id )) == S_OK)
@@ -2184,12 +2193,12 @@ static HRESULT build_dict( const BYTE *buf, ULONG buflen, struct dictionary *dic
     {
         if ((hr = read_size( &ptr, buflen, &size )) != S_OK)
         {
-            clear_dict( dict );
+            init_dict( dict, 0 );
             return hr;
         }
         if (size > buflen)
         {
-            clear_dict( dict );
+            init_dict( dict, 0 );
             return WS_E_INVALID_FORMAT;
         }
         buflen -= size;
@@ -2208,7 +2217,7 @@ static HRESULT build_dict( const BYTE *buf, ULONG buflen, struct dictionary *dic
         if ((hr = insert_string( dict, bytes, size, index, NULL )) != S_OK)
         {
             free( bytes );
-            clear_dict( dict );
+            init_dict( dict, 0 );
             return hr;
         }
         ptr += size;
@@ -2216,7 +2225,7 @@ static HRESULT build_dict( const BYTE *buf, ULONG buflen, struct dictionary *dic
     return S_OK;
 
 error:
-    clear_dict( dict );
+    init_dict( dict, 0 );
     return hr;
 }
 
diff --git a/dlls/webservices/string.c b/dlls/webservices/string.c
index 3ecdcea85a4..34e67101e66 100644
--- a/dlls/webservices/string.c
+++ b/dlls/webservices/string.c
@@ -131,7 +131,7 @@ static HRESULT grow_dict( struct dictionary *dict, ULONG size )
     return S_OK;
 }
 
-void clear_dict( struct dictionary *dict )
+void init_dict( struct dictionary *dict, ULONG str_bytes_max )
 {
     ULONG i;
     assert( !dict->dict.isConst );
@@ -145,6 +145,8 @@ void clear_dict( struct dictionary *dict )
     dict->sequence = NULL;
     dict->current_sequence = 0;
     dict->size = 0;
+    dict->str_bytes = 0;
+    dict->str_bytes_max = str_bytes_max;
 }
 
 HRESULT insert_string( struct dictionary *dict, unsigned char *data, ULONG len, int i, ULONG *ret_id )
@@ -162,6 +164,7 @@ HRESULT insert_string( struct dictionary *dict, unsigned char *data, ULONG len,
     dict->dict.strings[id].dictionary = &dict->dict;
     dict->dict.strings[id].id         = id;
     dict->dict.stringCount++;
+    dict->str_bytes += len + 1;
 
     dict->sequence[id] = dict->current_sequence;
 
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index b352aa52d49..373ab6799a9 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -49,13 +49,15 @@ struct dictionary
     ULONG              size;
     ULONG              current_sequence;
     ULONG             *sequence;
+    ULONG              str_bytes;
+    ULONG              str_bytes_max;
 };
 extern struct dictionary dict_builtin DECLSPEC_HIDDEN;
 extern const struct dictionary dict_builtin_static DECLSPEC_HIDDEN;
 
 int find_string( const struct dictionary *, const unsigned char *, ULONG, ULONG * ) DECLSPEC_HIDDEN;
 HRESULT insert_string( struct dictionary *, unsigned char *, ULONG, int, ULONG * ) DECLSPEC_HIDDEN;
-void clear_dict( struct dictionary * ) DECLSPEC_HIDDEN;
+void init_dict( struct dictionary *, ULONG ) DECLSPEC_HIDDEN;
 HRESULT writer_set_lookup( WS_XML_WRITER *, BOOL ) DECLSPEC_HIDDEN;
 HRESULT writer_set_dict_callback( WS_XML_WRITER *, WS_DYNAMIC_STRING_CALLBACK, void * ) DECLSPEC_HIDDEN;
 
-- 
2.30.2




More information about the wine-devel mailing list