Skip to content

Commit

Permalink
fix for bug 1359 (#1593)
Browse files Browse the repository at this point in the history
  • Loading branch information
alteholz committed Jan 15, 2022
1 parent 5ed21bd commit 4e21b46
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
89 changes: 89 additions & 0 deletions base64.c
Expand Up @@ -40,6 +40,17 @@
#include "base64_luts.h"
#include <stdio.h>

/*
* as byteswap.h is not available on macos, add macro here
* Swap bytes in 16-bit value.
*/
//#define bswap_16(x) __builtin_bswap16 (x);
#define bswap_16(x) ((__uint16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))

#include <arpa/inet.h>
#define IS_BIG_ENDIAN (1 == htons(1))
#define IS_LITTLE_ENDIAN (!IS_BIG_ENDIAN)

/* convert inlen raw bytes at in to base64 string (NUL-terminated) at out.
* out size should be at least 4*inlen/3 + 4.
* return length of out (sans trailing NUL).
Expand Down Expand Up @@ -119,6 +130,10 @@ int from64tobits_fast(char *out, const char *in, int inlen)
in++;
inp = (uint16_t *)in;

if IS_BIG_ENDIAN {
inp[0]=bswap_16(inp[0]);
inp[1]=bswap_16(inp[1]);
}
s1 = rbase64lut[inp[0]];
s2 = rbase64lut[inp[1]];

Expand All @@ -143,6 +158,10 @@ int from64tobits_fast(char *out, const char *in, int inlen)
if (in[0] == '\n')
in++;
inp = (uint16_t *)in;
if IS_BIG_ENDIAN {
inp[0]=bswap_16(inp[0]);
inp[1]=bswap_16(inp[1]);
}

s1 = rbase64lut[inp[0]];
s2 = rbase64lut[inp[1]];
Expand Down Expand Up @@ -172,6 +191,76 @@ int from64tobits_fast(char *out, const char *in, int inlen)
return outlen;
}

int from64tobits_fast_with_bug(char *out, const char *in, int inlen)
{
int outlen = 0;
uint8_t b1, b2, b3;
uint16_t s1, s2;
uint32_t n32;
int j;
int n = (inlen / 4) - 1;
uint16_t *inp = (uint16_t *)in;

for (j = 0; j < n; j++)
{
if (in[0] == '\n')
in++;
inp = (uint16_t *)in;

s1 = rbase64lut[inp[0]];
s2 = rbase64lut[inp[1]];

n32 = s1;
n32 <<= 10;
n32 |= s2 >> 2;

b3 = (n32 & 0x00ff);
n32 >>= 8;
b2 = (n32 & 0x00ff);
n32 >>= 8;
b1 = (n32 & 0x00ff);

out[0] = b1;
out[1] = b2;
out[2] = b3;

in += 4;
out += 3;
}
outlen = (inlen / 4 - 1) * 3;
if (in[0] == '\n')
in++;
inp = (uint16_t *)in;

s1 = rbase64lut[inp[0]];
s2 = rbase64lut[inp[1]];

n32 = s1;
n32 <<= 10;
n32 |= s2 >> 2;

b3 = (n32 & 0x00ff);
n32 >>= 8;
b2 = (n32 & 0x00ff);
n32 >>= 8;
b1 = (n32 & 0x00ff);

*out++ = b1;
outlen++;
if ((inp[1] & 0x00FF) != 0x003D)
{
*out++ = b2;
outlen++;
if ((inp[1] & 0xFF00) != 0x3D00)
{
*out++ = b3;
outlen++;
}
}
return outlen;
}


#ifdef BASE64_PROGRAM
/* standalone program that converts to/from base64.
* cc -o base64 -DBASE64_PROGRAM base64.c
Expand Down
1 change: 1 addition & 0 deletions base64.h
Expand Up @@ -57,6 +57,7 @@ extern int to64frombits(unsigned char *out, const unsigned char *in, int inlen);

extern int from64tobits(char *out, const char *in);
extern int from64tobits_fast(char *out, const char *in, int inlen);
extern int from64tobits_fast_with_bug(char *out, const char *in, int inlen);

/*@}*/

Expand Down
37 changes: 37 additions & 0 deletions test/core/test_base64.cpp
Expand Up @@ -78,3 +78,40 @@ TEST(CORE_BASE64, Test_from64tobits_fast)
ASSERT_EQ(out_len, res_len);
ASSERT_STREQ(out_msg, res_msg);
}

TEST(CORE_BASE64, Test_from64tobits_fast_time)
{
const char inp_msg[] = "Rk9PQkFSQkFa";
const size_t inp_len = sizeof(inp_msg) - 1;

const char out_msg[] = "FOOBARBAZ";
const size_t out_len = sizeof(out_msg) - 1;

char res_msg[out_len + 1] = {0,};
size_t res_len = 0;

int i, iterations = 1000 * 1000 * 10;

for (i=0; i<iterations; i++) {
res_len = from64tobits_fast(res_msg, inp_msg, inp_len);
}
}

TEST(CORE_BASE64, Test_from64tobits_fast_with_bug_time)
{
const char inp_msg[] = "Rk9PQkFSQkFa";
const size_t inp_len = sizeof(inp_msg) - 1;

const char out_msg[] = "FOOBARBAZ";
const size_t out_len = sizeof(out_msg) - 1;

char res_msg[out_len + 1] = {0,};
size_t res_len = 0;

int i, iterations = 1000 * 1000 * 10;

for (i=0; i<iterations; i++) {
res_len = from64tobits_fast_with_bug(res_msg, inp_msg, inp_len);
}
}

0 comments on commit 4e21b46

Please sign in to comment.