diff --git a/ext/standard/string.c b/ext/standard/string.c index 0aade780856b9..1e0a6de544c47 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -150,10 +150,12 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t * */ static char *php_hex2bin(const unsigned char *old, const size_t oldlen, size_t *newlen) { - size_t target_length = oldlen >> 1; + size_t target_length = (oldlen + 1) >> 1; register unsigned char *str = (unsigned char *)safe_emalloc(target_length, sizeof(char), 1); size_t i, j; - for (i = j = 0; i < target_length; i++) { + /* if we have an odd length, point to the end of the string to distinguish the special case */ + j = oldlen & 1 ? oldlen : 0; + for (i = 0; i < target_length; i++) { char c = old[j++]; if (c >= '0' && c <= '9') { str[i] = (c - '0') << 4; @@ -161,6 +163,10 @@ static char *php_hex2bin(const unsigned char *old, const size_t oldlen, size_t * str[i] = (c - 'a' + 10) << 4; } else if (c >= 'A' && c <= 'F') { str[i] = (c - 'A' + 10) << 4; + } else if(c == '\0') { + /* odd length, put the first 4 bits to 0 and restart at the beginning of the string */ + str[i] = 0; + j= 0; } else { efree(str); return NULL;