From b8ba1cb23590afd6d44c376481aef371b9c87457 Mon Sep 17 00:00:00 2001 From: Gilles Meier Date: Sun, 8 Apr 2012 14:47:51 +0200 Subject: [PATCH 1/2] Patch for bug #61660 When the hexadecimal string has an odd length, the resulting binary data must be left padded with 0s in order to be aligned on 8 bits. To avoid extraneous if test on each iteration, we distinguish the special case by pointing the source data iterator the the NUL bytes at the end which we can then detect and act accordingly. --- ext/standard/string.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 0aade780856b9..ffa7b44a9908a 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 + 1: 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; From 7f35ddc643cef86a5f9097949304f7ddb337b1fb Mon Sep 17 00:00:00 2001 From: Gilles Meier Date: Sun, 8 Apr 2012 15:18:45 +0200 Subject: [PATCH 2/2] bugfix: oldlen is already the index for the end of the string, ne need to add one --- ext/standard/string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index ffa7b44a9908a..1e0a6de544c47 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -154,7 +154,7 @@ static char *php_hex2bin(const unsigned char *old, const size_t oldlen, size_t * register unsigned char *str = (unsigned char *)safe_emalloc(target_length, sizeof(char), 1); size_t i, j; /* if we have an odd length, point to the end of the string to distinguish the special case */ - j = oldlen & 1 ? oldlen + 1: 0; + j = oldlen & 1 ? oldlen : 0; for (i = 0; i < target_length; i++) { char c = old[j++]; if (c >= '0' && c <= '9') {