diff options
-rw-r--r-- | include/base64.h | 3 | ||||
-rw-r--r-- | mysys/base64.c | 65 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 3 | ||||
-rw-r--r-- | storage/ndb/src/mgmapi/mgmapi.cpp | 2 | ||||
-rw-r--r-- | unittest/mysys/base64-t.c | 2 |
5 files changed, 54 insertions, 21 deletions
diff --git a/include/base64.h b/include/base64.h index 4653e824a9a..a6bffebfe07 100644 --- a/include/base64.h +++ b/include/base64.h @@ -39,7 +39,8 @@ int base64_encode(const void *src, size_t src_len, char *dst); /* Decode a base64 string into data */ -int base64_decode(const char *src, size_t src_len, void *dst); +int base64_decode(const char *src, size_t src_len, + void *dst, const char **end_ptr); #ifdef __cplusplus diff --git a/mysys/base64.c b/mysys/base64.c index 610797dd2ce..6c338b83868 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -125,44 +125,69 @@ pos(unsigned char c) /* Decode a base64 string - Note: We require that dst is pre-allocated to correct size. - See base64_needed_decoded_length(). - - RETURN Number of bytes produced in dst or -1 in case of failure + SYNOPSIS + base64_decode() + src Pointer to base64-encoded string + len Length of string at 'src' + dst Pointer to location where decoded data will be stored + end_ptr Pointer to variable that will refer to the character + after the end of the encoded data that were decoded. Can + be NULL. + + DESCRIPTION + + The base64-encoded data in the range ['src','*end_ptr') will be + decoded and stored starting at 'dst'. The decoding will stop + after 'len' characters have been read from 'src', or when padding + occurs in the base64-encoded data. In either case: if 'end_ptr' is + non-null, '*end_ptr' will be set to point to the character after + the last read character, even in the presence of error. + + NOTE + We require that 'dst' is pre-allocated to correct size. + + SEE ALSO + base64_needed_decoded_length(). + + RETURN VALUE + Number of bytes written at 'dst' or -1 in case of failure */ int -base64_decode(const char *src, size_t size, void *dst) +base64_decode(const char *const src_base, size_t const len, + void *dst, const char **end_ptr) { char b[3]; size_t i= 0; char *dst_base= (char *)dst; + char const *src= src_base; char *d= dst_base; size_t j; - while (i < size) + while (i < len) { unsigned c= 0; size_t mark= 0; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); - if (* src != '=') + if (*src != '=') c += pos(*src++); else { - i= size; + src += 2; /* There should be two bytes padding */ + i= len; mark= 2; c <<= 6; goto end; @@ -170,13 +195,14 @@ base64_decode(const char *src, size_t size, void *dst) c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); if (*src != '=') c += pos(*src++); else { - i= size; + src += 1; /* There should be one byte padding */ + i= len; mark= 1; goto end; } @@ -191,11 +217,14 @@ base64_decode(const char *src, size_t size, void *dst) *d++= b[j]; } - if (i != size) - { - return -1; - } - return d - dst_base; + if (end_ptr != NULL) + *end_ptr= src; + + /* + The variable 'i' is set to 'len' when padding has been read, so it + does not actually reflect the number of bytes read from 'src'. + */ + return i != len ? -1 : d - dst_base; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 01fcfd1adf9..b37459f5cbf 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5837,3 +5837,6 @@ ER_PARTITION_MERGE_ERROR swe "%s kan inte användas i en partitionerad tabell" ER_RBR_NOT_AVAILABLE eng "The server was not built with row-based replication" +ER_BASE64_DECODE_ERROR + eng "Decoding of base64 string failed" + swe "Avkodning av base64 sträng misslyckades" diff --git a/storage/ndb/src/mgmapi/mgmapi.cpp b/storage/ndb/src/mgmapi/mgmapi.cpp index 6dfb48667aa..79ec99a1a10 100644 --- a/storage/ndb/src/mgmapi/mgmapi.cpp +++ b/storage/ndb/src/mgmapi/mgmapi.cpp @@ -1771,7 +1771,7 @@ ndb_mgm_get_configuration(NdbMgmHandle handle, unsigned int version) { break; void *tmp_data = malloc(base64_needed_decoded_length((size_t) (len - 1))); - const int res = base64_decode(buf64, len-1, tmp_data); + const int res = base64_decode(buf64, len-1, tmp_data, NULL); delete[] buf64; UtilBuffer tmp; tmp.append((void *) tmp_data, res); diff --git a/unittest/mysys/base64-t.c b/unittest/mysys/base64-t.c index 6d85964b20d..ccec0c77086 100644 --- a/unittest/mysys/base64-t.c +++ b/unittest/mysys/base64-t.c @@ -54,7 +54,7 @@ main(void) /* Decode */ dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); - dst_len= base64_decode(str, strlen(str), dst); + dst_len= base64_decode(str, strlen(str), dst, NULL); ok(dst_len == src_len, "Comparing lengths"); cmp= memcmp(src, dst, src_len); |