From 9b6b52cc8c5838cffeee9388c04890fe1eb73b52 Mon Sep 17 00:00:00 2001 From: Evan Miller Date: Thu, 6 Aug 2020 12:34:09 -0400 Subject: [PATCH] Fix buffer overflow in mdb_numeric_to_string brianb/mdbtools#124 --- src/libmdb/money.c | 81 +++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/src/libmdb/money.c b/src/libmdb/money.c index 3e307bb..97f9247 100644 --- a/src/libmdb/money.c +++ b/src/libmdb/money.c @@ -23,15 +23,16 @@ #include "dmalloc.h" #endif -#define MAX_NUMERIC_PRECISION 28 +#define MAX_MONEY_PRECISION 20 +#define MAX_NUMERIC_PRECISION 40 /* ** these routines are copied from the freetds project which does something ** very similiar */ -static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier); -static int do_carry(unsigned char *product); -static char *array_to_string(unsigned char *array, int unsigned scale, int neg); +static int multiply_byte(unsigned char *product, int num, unsigned char *multiplier, size_t len); +static int do_carry(unsigned char *product, size_t len); +static char *array_to_string(unsigned char *array, size_t len, int unsigned scale, int neg); /** * mdb_money_to_string @@ -45,17 +46,15 @@ char *mdb_money_to_string(MdbHandle *mdb, int start) const int num_bytes=8, scale=4; int i; int neg=0; - unsigned char multiplier[MAX_NUMERIC_PRECISION], temp[MAX_NUMERIC_PRECISION]; - unsigned char product[MAX_NUMERIC_PRECISION]; - unsigned char bytes[num_bytes]; + unsigned char multiplier[MAX_MONEY_PRECISION] = { 1 }; + unsigned char temp[MAX_MONEY_PRECISION]; + unsigned char product[MAX_MONEY_PRECISION] = { 0 }; + unsigned char bytes[num_bytes]; - memset(multiplier,0,MAX_NUMERIC_PRECISION); - memset(product,0,MAX_NUMERIC_PRECISION); - multiplier[0]=1; - memcpy(bytes, mdb->pg_buf + start, num_bytes); + memcpy(bytes, mdb->pg_buf + start, num_bytes); /* Perform two's complement for negative numbers */ - if (bytes[num_bytes-1] & 0x80) { + if (bytes[num_bytes-1] & 0x80) { neg = 1; for (i=0;ipg_buf + start + 1, num_bytes); - /* Perform two's complement for negative numbers */ + /* Negative bit is stored in first byte */ if (mdb->pg_buf[start] & 0x80) neg = 1; for (i=0;i9) { product[j+1]+=product[j]/10; - product[j]=product[j]%10; + product[j]%=10; } } if (product[j]>9) { - product[j]=product[j]%10; + product[j]%=10; } return 0; } -static char *array_to_string(unsigned char *array, unsigned int scale, int neg) +static char *array_to_string(unsigned char *array, size_t len, unsigned int scale, int neg) { char *s; unsigned int top, i, j=0; - for (top=MAX_NUMERIC_PRECISION;(top>0) && (top-1>scale) && !array[top-1];top--); + for (top=len;(top>0) && (top-1>scale) && !array[top-1];top--); /* allocate enough space for all digits + minus sign + decimal point + trailing NULL byte */ - s = (char *) g_malloc(MAX_NUMERIC_PRECISION+3); + s = (char *) g_malloc(len+3); if (neg) s[j++] = '-';