Mercurial > libjeffpc
view tests/test_str2uint.c @ 674:a8663230bd14
int: add tests checking for str2uXX overflows
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 21 Feb 2019 19:18:52 -0500 |
parents | 927cbe0ea334 |
children | 19bcd869e80d |
line wrap: on
line source
/* * Copyright (c) 2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include <jeffpc/int.h> #include <jeffpc/types.h> #include <jeffpc/error.h> #include "test.c" struct res { int ret; uint64_t out; }; struct run { const char *in; struct res out[3][3]; /* out[base][size] */ }; #define B8 0 #define B10 1 #define B16 2 static const int bases[] = { [B8] = 8, [B10] = 10, [B16] = 16, }; #define SZ16 0 #define SZ32 1 #define SZ64 2 static const int sizes[] = { [SZ16] = 16, [SZ32] = 32, [SZ64] = 64, }; #define ENT(v_s16, v_s32, v_s64, r_s16, r_s32, r_s64) \ { \ [SZ16] = { .ret = (r_s16), .out = (v_s16), }, \ [SZ32] = { .ret = (r_s32), .out = (v_s32), }, \ [SZ64] = { .ret = (r_s64), .out = (v_s64), }, \ } static const struct run runs[] = { { .in = "", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), }, /* * Check various well-formed (in at least one base) inputs */ { .in = "0", .out[B8] = ENT(0, 0, 0, 0, 0, 0), .out[B10] = ENT(0, 0, 0, 0, 0, 0), .out[B16] = ENT(0, 0, 0, 0, 0, 0), }, { .in = "00", .out[B8] = ENT(0, 0, 0, 0, 0, 0), .out[B10] = ENT(0, 0, 0, 0, 0, 0), .out[B16] = ENT(0, 0, 0, 0, 0, 0), }, { .in = "0x0", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0, 0, 0, 0, 0, 0), }, { .in = "5", .out[B8] = ENT(5, 5, 5, 0, 0, 0), .out[B10] = ENT(5, 5, 5, 0, 0, 0), .out[B16] = ENT(5, 5, 5, 0, 0, 0), }, { .in = "8", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(8, 8, 8, 0, 0, 0), .out[B16] = ENT(8, 8, 8, 0, 0, 0), }, { .in = "0x8", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(8, 8, 8, 0, 0, 0), }, { .in = "A", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, { .in = "a", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, { .in = "0XA", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, { .in = "0Xa", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, { .in = "0xA", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, { .in = "0xa", .out[B8] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B10] = ENT(0, 0, 0, -EINVAL, -EINVAL, -EINVAL), .out[B16] = ENT(0xa, 0xa, 0xa, 0, 0, 0), }, /* * Check various well-formed inputs for overflows */ { .in = "7", .out[B8] = ENT(7, 7, 7, 0, 0, 0), .out[B10] = ENT(7, 7, 7, 0, 0, 0), .out[B16] = ENT(7, 7, 7, 0, 0, 0), }, { .in = "70", .out[B8] = ENT(070, 070, 070, 0, 0, 0), .out[B10] = ENT(70, 70, 70, 0, 0, 0), .out[B16] = ENT(0x70, 0x70, 0x70, 0, 0, 0), }, { .in = "7070", .out[B8] = ENT(07070, 07070, 07070, 0, 0, 0), .out[B10] = ENT(7070, 7070, 7070, 0, 0, 0), .out[B16] = ENT(0x7070, 0x7070, 0x7070, 0, 0, 0), }, { .in = "70707", .out[B8] = ENT(070707, 070707, 070707, 0, 0, 0), .out[B10] = ENT( 0, 70707, 70707, -ERANGE, 0, 0), .out[B16] = ENT( 0, 0x70707, 0x70707, -ERANGE, 0, 0), }, { .in = "707070", .out[B8] = ENT(0, 0707070, 0707070, -ERANGE, 0, 0), .out[B10] = ENT(0, 707070, 707070, -ERANGE, 0, 0), .out[B16] = ENT(0, 0x707070, 0x707070, -ERANGE, 0, 0), }, { .in = "70707070", .out[B8] = ENT(0, 070707070, 070707070, -ERANGE, 0, 0), .out[B10] = ENT(0, 70707070, 70707070, -ERANGE, 0, 0), .out[B16] = ENT(0, 0x70707070, 0x70707070, -ERANGE, 0, 0), }, { .in = "7070707070", .out[B8] = ENT(0, 07070707070, 07070707070, -ERANGE, 0, 0), .out[B10] = ENT(0, 0, 7070707070, -ERANGE, -ERANGE, 0), .out[B16] = ENT(0, 0, 0x7070707070, -ERANGE, -ERANGE, 0), }, { .in = "707070707070", .out[B8] = ENT(0, 0, 0707070707070, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 707070707070, -ERANGE, -ERANGE, 0), .out[B16] = ENT(0, 0, 0x707070707070, -ERANGE, -ERANGE, 0), }, { .in = "70707070707070", .out[B8] = ENT(0, 0, 070707070707070, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 70707070707070, -ERANGE, -ERANGE, 0), .out[B16] = ENT(0, 0, 0x70707070707070, -ERANGE, -ERANGE, 0), }, { .in = "7070707070707070", .out[B8] = ENT(0, 0, 07070707070707070, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 7070707070707070, -ERANGE, -ERANGE, 0), .out[B16] = ENT(0, 0, 0x7070707070707070, -ERANGE, -ERANGE, 0), }, { .in = "707070707070707070", .out[B8] = ENT(0, 0, 0707070707070707070, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 707070707070707070, -ERANGE, -ERANGE, 0), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "70707070707070707070", .out[B8] = ENT(0, 0, 070707070707070707070, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "707070707070707070707", .out[B8] = ENT(0, 0, 0707070707070707070707, -ERANGE, -ERANGE, 0), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "7070707070707070707070", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, /* * Check negative numbers */ { .in = "-0", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-1", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-8", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-A", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-a", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-0XA", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-0Xa", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-0xA", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, { .in = "-0xa", .out[B8] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B10] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), .out[B16] = ENT(0, 0, 0, -ERANGE, -ERANGE, -ERANGE), }, /* * FIXME: more test cases * - check inputs with leading garbage * - check inputs with trailing garbage */ }; #define TEST(i, bidx, szidx, expr, type) \ do { \ const char *in = runs[i].in; \ const struct res *res = &runs[i].out[bidx][szidx]; \ const int base = bases[bidx]; \ const int size = sizes[szidx]; \ type tmp; \ uint64_t out; \ int ret; \ \ fprintf(stderr, "%2d: ... %s -> ", (i), #expr); \ \ ret = (expr); \ out = tmp; \ \ /* print the result we got */ \ if (ret) { \ fprintf(stderr, "ret=%d", ret); \ } else { \ static const char *fmts[] = { \ [B8] = "%#0*"PRIo64, \ [B10] = "%#0*"PRIu64, \ [B16] = "%#0*"PRIx64, \ }; \ int width = 2 * size / 8; \ \ if (base == 8) \ width++; /* extra leading 0 */ \ else if (base == 16) \ width += 2; /* leading 0x */ \ \ fprintf(stderr, "out="); \ fprintf(stderr, fmts[bidx], width, out); \ } \ fprintf(stderr, "..."); \ \ check_rets(res->ret, ret, "str2u%d", size); \ \ if (!ret) \ ASSERT3U(out, ==, res->out); \ \ fprintf(stderr, "ok.\n"); \ } while (0) void test(void) { int i; for (i = 0; i < ARRAY_LEN(runs); i++) { fprintf(stderr, "%2d: in='%s'...\n", i, runs[i].in); /* test simple base 10 parsing */ TEST(i, B10, SZ16, str2u16(in, &tmp), uint16_t); TEST(i, B10, SZ32, str2u32(in, &tmp), uint32_t); TEST(i, B10, SZ64, str2u64(in, &tmp), uint64_t); /* test underlying function with all bases */ TEST(i, B8, SZ16, str2u16_base(in, &tmp, 8), uint16_t); TEST(i, B8, SZ32, str2u32_base(in, &tmp, 8), uint32_t); TEST(i, B8, SZ64, str2u64_base(in, &tmp, 8), uint64_t); TEST(i, B10, SZ16, str2u16_base(in, &tmp, 10), uint16_t); TEST(i, B10, SZ32, str2u32_base(in, &tmp, 10), uint32_t); TEST(i, B10, SZ64, str2u64_base(in, &tmp, 10), uint64_t); TEST(i, B16, SZ16, str2u16_base(in, &tmp, 16), uint16_t); TEST(i, B16, SZ32, str2u32_base(in, &tmp, 16), uint32_t); TEST(i, B16, SZ64, str2u64_base(in, &tmp, 16), uint64_t); } }