diff options
Diffstat (limited to 'ext/standard/base64.c')
-rw-r--r-- | ext/standard/base64.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/ext/standard/base64.c b/ext/standard/base64.c index f6dbdf577a..cd6bac0b3d 100644 --- a/ext/standard/base64.c +++ b/ext/standard/base64.c @@ -144,17 +144,7 @@ PHPAPI zend_string *php_base64_decode_ex(const unsigned char *str, size_t length /* run through the whole string, converting as we go */ while (length-- > 0) { ch = *current++; - /* stop on null byte in non-strict mode (FIXME: is this really desired?) */ - if (ch == 0 && !strict) { - break; - } if (ch == base64_pad) { - /* fail if the padding character is second in a group (like V===) */ - /* FIXME: why do we still allow invalid padding in other places in the middle of the string? */ - if (i % 4 == 1) { - zend_string_free(result); - return NULL; - } padding++; continue; } @@ -172,8 +162,7 @@ PHPAPI zend_string *php_base64_decode_ex(const unsigned char *str, size_t length } /* fail on bad characters or if any data follows padding */ if (ch == -2 || padding) { - zend_string_free(result); - return NULL; + goto fail; } } @@ -195,11 +184,24 @@ PHPAPI zend_string *php_base64_decode_ex(const unsigned char *str, size_t length } i++; } + /* fail if the input is truncated (only one char in last group) */ + if (strict && i % 4 == 1) { + goto fail; + } + /* fail if the padding length is wrong (not VV==, VVV=), but accept zero padding + * RFC 4648: "In some circumstances, the use of padding [--] is not required" */ + if (strict && padding && (padding > 2 || (i + padding) % 4 != 0)) { + goto fail; + } ZSTR_LEN(result) = j; ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0'; return result; + +fail: + zend_string_free(result); + return NULL; } /* }}} */ |