summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/base64.h3
-rw-r--r--mysys/base64.c65
-rw-r--r--sql/share/errmsg.txt3
-rw-r--r--storage/ndb/src/mgmapi/mgmapi.cpp2
-rw-r--r--unittest/mysys/base64-t.c2
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);