]> granicus.if.org Git - php/commitdiff
Add support for string dictionaries, fix array dictionaries ({de,in}flate)
authorBob Weinand <bobwei9@hotmail.com>
Thu, 21 May 2015 02:17:17 +0000 (04:17 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Thu, 21 May 2015 02:17:17 +0000 (04:17 +0200)
ext/zlib/tests/dictionary_usage.phpt
ext/zlib/zlib.c

index 8ffa9e8bcd9b496d12c1037b290c4a5ffb242ca1..f7ef3b3a9cc0c6bbf4a1995658b02e336a2934c9 100644 (file)
@@ -9,6 +9,10 @@ $r = deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => $dict]);
 $a = deflate_add($r, "abdcde", ZLIB_FINISH);
 var_dump($a);
 
+$r = deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => implode("\0", $dict)."\0"]);
+$dictStr_a = deflate_add($r, "abdcde", ZLIB_FINISH);
+var_dump($dictStr_a === $a);
+
 $r = inflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => $dict]);
 var_dump(inflate_add($r, $a, ZLIB_FINISH));
 
@@ -19,6 +23,7 @@ var_dump(inflate_add($r, $a, ZLIB_FINISH));
 ?>
 --EXPECTF--
 string(%d) "%s"
+bool(true)
 string(6) "abdcde"
 
 Warning: inflate_add(): dictionary does not match expected dictionary (incorrect adler32 hash) in %s on line %d
index 81694243627bda152b419e2e5117127a7ea80242..b4b95e85a5242835aa3e42a046d85ccf3843c006 100644 (file)
@@ -759,60 +759,87 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict,
        zval *option_buffer;
 
        if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("dictionary"))) != NULL) {
-               HashTable *dictionary;
-
                ZVAL_DEREF(option_buffer);
-               if (Z_TYPE_P(option_buffer) != IS_ARRAY) {
-                       php_error_docref(NULL, E_WARNING, "dictionary must be of type array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer)));
-                       return 0;
-               }
-               dictionary = Z_ARR_P(option_buffer);
-
-               if (zend_hash_num_elements(dictionary) > 0) {
-                       char *dictptr;
-                       zval *cur;
-                       zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
-                       zend_string **end, **ptr = strings - 1;
-
-                       ZEND_HASH_FOREACH_VAL(dictionary, cur) {
+               switch (Z_TYPE_P(option_buffer)) {
+                       case IS_STRING: {
+                               zend_string *str = Z_STR_P(option_buffer);
                                int i;
-
-                               *++ptr = zval_get_string(cur);
-                               if (!*ptr || (*ptr)->len == 0) {
-                                       if (*ptr) {
-                                               efree(*ptr);
-                                       }
-                                       while (--ptr >= strings) {
-                                               efree(ptr);
+                               zend_bool last_null = 1;
+
+                               for (i = 0; i < str->len; i++) {
+                                       if (str->val[i]) {
+                                               last_null = 0;
+                                       } else {
+                                               if (last_null) {
+                                                       php_error_docref(NULL, E_WARNING, "dictionary string must not contain empty entries (two consecutive NULL-bytes or one at the very beginning)");
+                                                       return 0;
+                                               }
+                                               last_null = 1;
                                        }
-                                       efree(strings);
-                                       php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
-                                       return 0;
                                }
-                               for (i = 0; i < (*ptr)->len; i++) {
-                                       if ((*ptr)->val[i] == 0) {
-                                               do {
-                                                       efree(ptr);
-                                               } while (--ptr >= strings);
-                                               efree(strings);
-                                               php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte");
-                                               return 0;
-                                       }
+                               if (!last_null) {
+                                       php_error_docref(NULL, E_WARNING, "dictionary string must be NULL-byte terminated (each dictionary entry has to be NULL-terminated)");
+                               }
+
+                               *dict = emalloc(str->len);
+                               memcpy(*dict, str->val, str->len);
+                               *dictlen = str->len;
+                       } break;
+
+                       case IS_ARRAY: {
+                               HashTable *dictionary = Z_ARR_P(option_buffer);
+
+                               if (zend_hash_num_elements(dictionary) > 0) {
+                                       char *dictptr;
+                                       zval *cur;
+                                       zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
+                                       zend_string **end, **ptr = strings - 1;
+
+                                       ZEND_HASH_FOREACH_VAL(dictionary, cur) {
+                                               int i;
+
+                                               *++ptr = zval_get_string(cur);
+                                               if (!*ptr || (*ptr)->len == 0) {
+                                                       if (*ptr) {
+                                                               efree(*ptr);
+                                                       }
+                                                       while (--ptr >= strings) {
+                                                               efree(ptr);
+                                                       }
+                                                       efree(strings);
+                                                       php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
+                                                       return 0;
+                                               }
+                                               for (i = 0; i < (*ptr)->len; i++) {
+                                                       if ((*ptr)->val[i] == 0) {
+                                                               do {
+                                                                       efree(ptr);
+                                                               } while (--ptr >= strings);
+                                                               efree(strings);
+                                                               php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte");
+                                                               return 0;
+                                                       }
+                                               }
+
+                                               *dictlen += (*ptr)->len + 1;
+                                       } ZEND_HASH_FOREACH_END();
+
+                                       dictptr = *dict = emalloc(*dictlen);
+                                       ptr = strings;
+                                       end = strings + zend_hash_num_elements(dictionary);
+                                       do {
+                                               memcpy(dictptr, (*ptr)->val, (*ptr)->len);
+                                               dictptr += (*ptr)->len;
+                                               *dictptr++ = 0;
+                                               zend_string_release(*ptr);
+                                       } while (++ptr != end);
+                                       efree(strings);
                                }
+                       } break;
 
-                               *dictlen += (*ptr)->len + 1;
-                       } ZEND_HASH_FOREACH_END();
-
-                       dictptr = *dict = emalloc(*dictlen);
-                       ptr = strings;
-                       end = strings + zend_hash_num_elements(dictionary);
-                       do {
-                               memcpy(dictptr, *ptr, (*ptr)->len);
-                               dictptr += (*ptr)->len;
-                               *dictptr++ = 0;
-                               zend_string_release(*ptr);
-                       } while (++ptr != end);
-                       efree(strings);
+                       default:
+                               php_error_docref(NULL, E_WARNING, "dictionary must be of type zero-terminated string or array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer)));
+                               return 0;
                }
        }