diff options
author | Florian Weimer <fweimer@redhat.com> | 2016-04-25 14:10:26 +0200 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2016-04-25 14:10:26 +0200 |
commit | fdcf1c9480342d9f5fc2d23f142d621bcb4d00a4 (patch) | |
tree | 1678f802177bb5f37a058e857a43da5363ab5d8e /stdio-common/tst-vfprintf-width-prec.c | |
parent | a5507dfa60a8b92ba52dadabea88e2b5d91da655 (diff) | |
download | glibc-fdcf1c9480342d9f5fc2d23f142d621bcb4d00a4.tar.gz glibc-fdcf1c9480342d9f5fc2d23f142d621bcb4d00a4.tar.xz glibc-fdcf1c9480342d9f5fc2d23f142d621bcb4d00a4.zip |
vfprintf: Fix memory with large width and precision [BZ #19931]
Free a previously allocated work buffer if it is not large enough.
Diffstat (limited to 'stdio-common/tst-vfprintf-width-prec.c')
-rw-r--r-- | stdio-common/tst-vfprintf-width-prec.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/stdio-common/tst-vfprintf-width-prec.c b/stdio-common/tst-vfprintf-width-prec.c new file mode 100644 index 0000000000..28927419ee --- /dev/null +++ b/stdio-common/tst-vfprintf-width-prec.c @@ -0,0 +1,107 @@ +/* Test for memory leak with large width and precision. + Copyright (C) 1991-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <mcheck.h> +#include <stdio.h> +#include <sys/resource.h> +#include <wchar.h> + +static int +do_test (void) +{ + mtrace (); + + int ret; + { + char *result; + ret = asprintf (&result, "%133000.133001x", 17); + if (ret < 0) + { + printf ("error: asprintf: %m\n"); + return 1; + } + free (result); + } + { + wchar_t *result = calloc (ret + 1, sizeof (wchar_t)); + if (result == NULL) + { + printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t)); + return 1; + } + + ret = swprintf (result, ret + 1, L"%133000.133001x", 17); + if (ret < 0) + { + printf ("error: swprintf: %d (%m)\n", ret); + return 1; + } + free (result); + } + + /* Limit the size of the process, so that the second allocation will + fail. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("getrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + long target = 200 * 1024 * 1024; + if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target) + { + limit.rlim_cur = target; + if (setrlimit (RLIMIT_AS, &limit) != 0) + { + printf ("setrlimit (RLIMIT_AS) failed: %m\n"); + return 1; + } + } + } + + { + char *result; + ret = asprintf (&result, "%133000.999999999x", 17); + if (ret >= 0) + { + printf ("error: asprintf: incorrect result %d\n", ret); + return 1; + } + } + { + wchar_t result[100]; + if (result == NULL) + { + printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t)); + return 1; + } + + ret = swprintf (result, 100, L"%133000.999999999x", 17); + if (ret >= 0) + { + printf ("error: swprintf: incorrect result %d\n", ret); + return 1; + } + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |