Commit ddcad361 authored by Arun Kuruvila's avatar Arun Kuruvila

Bug #21503595 : --QUERY-ALLOC-BLOCK-SIZE=-1125899906842624 +

                PID_FILE CHECK LEADS TO OOM SIG 11

Description:- A server started with 'query_alloc_block_size'
option set to a certain range of negative values on a
machine without enough memory may lead to OOM.

Analysis:- Server uses 'strtoull()' to convert server
variable values of type 'GET_UINT', 'GET_ULONG' or 'GET_ULL'
from string to unsigned long long. According to the man
page, 'strtoull()' function returns either the result of the
conversion or, if there was a leading minus sign, the
negation of the result of the conversion represented as an
unsigned value, unless the original(nonnegated) value would
overflow; in the latter case, strtoull() returns ULLONG_MAX
and sets errno to ERANGE. So 'strtoull()' converts a small
negative value to a larger postive value. For example string
'-1125899906842624' will be converted to an unsigned value,
'18445618173802708992' (ulonglong typecast of
'-1125899906842624'). So a
server started with 'query_alloc_block_size' set to
"-1125899906842624" on a machine without enough memory will
lead to OOM since server allocates '18445618173802708992'
bytes(17178820608 GB) for query allocation block.

Fix:- When server is started with any server variable, of
type "GET_UINT", "GET_ULONG" or "GET_ULL", set to a negative
value, a warning, "option xxx: value -yyy adjusted to zzz"
is thrown and the value is adjusted to the lowest possible
value for that variable. The dynamic server variable which
is configured through the client exhibit the same behavior
as fix made for variables configured during the server
start up.
parent 0bb654b8
/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -1005,6 +1005,14 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
return num;
}
static inline my_bool is_negative_num(char* num)
{
while (my_isspace(&my_charset_latin1, *num))
num++;
return (*num == '-');
}
/*
function: getopt_ull
......@@ -1014,7 +1022,20 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err)
{
ulonglong num= eval_num_suffix(arg, err, (char*) optp->name);
char buf[255];
ulonglong num;
/* If a negative number is specified as a value for the option. */
if (arg == NULL || is_negative_num(arg) == TRUE)
{
num= (ulonglong) optp->min_value;
my_getopt_error_reporter(WARNING_LEVEL,
"option '%s': value %s adjusted to %s",
optp->name, arg, ullstr(num, buf));
}
else
num= eval_num_suffix(arg, err, (char*) optp->name);
return getopt_ull_limit_value(num, optp, NULL);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment