From fa25921b59aacdc6be050653f6cce17df12c6937 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 10 Dec 2015 11:22:53 +0100 Subject: [PATCH] MDEV-8407 Numeric errors, server crash with COLUMN_JSON() on DECIMAL with precision > 40 In fact it was error in decimal library (incorrect processing of buffer overflow) invisible from other server parts because of buffer allocation and precision tests. --- strings/decimal.c | 3 ++- unittest/my_decimal/my_decimal-t.cc | 34 +++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/strings/decimal.c b/strings/decimal.c index 07ccc537e47..8dbe1bd57f4 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -383,7 +383,8 @@ int decimal2string(const decimal_t *from, char *to, int *to_len, } else frac-=j; - len= from->sign + intg_len + test(frac) + frac_len; + frac_len= frac; + len= from->sign + intg_len + test(frac) + frac; } *to_len=len; s[len]=0; diff --git a/unittest/my_decimal/my_decimal-t.cc b/unittest/my_decimal/my_decimal-t.cc index 48d00465af9..92c4bdee8e4 100644 --- a/unittest/my_decimal/my_decimal-t.cc +++ b/unittest/my_decimal/my_decimal-t.cc @@ -61,12 +61,42 @@ test_copy_and_compare() } +static int +test_decimal2string() +{ + decimal_t d1; + decimal_digit_t buffer[DECIMAL_BUFF_LENGTH+2]; + char *str_end; + const char strnum[]= "0.1234567890123456789012345678901234567890123467"; + char strbuff[50]; + int len= 40; + int i; + + bzero(strbuff, sizeof(strbuff)); + str_end= (char *)(strnum + (sizeof(strnum) - 1)); + + d1.len= DECIMAL_BUFF_LENGTH + 2; + d1.buf= buffer; + + string2decimal(strnum, &d1, &str_end); + decimal2string(&d1, strbuff, &len, 0, 0, 'X'); + + /* last digit is not checked due to possible rounding */ + for (i= 0; i < 38 && strbuff[i] == strnum[i]; i++); + ok(i == 38, "Number"); + for (i= 39; i < 50 && strbuff[i] == 0; i++); + ok(i == 50, "No overrun"); + + return 0; + +} int main() { - plan(13); + plan(15); diag("Testing my_decimal constructor and assignment operators"); test_copy_and_compare(); - + test_decimal2string(); + return exit_status(); }