From 888f63a9c8b4a848d1049871c05ce3656c015ffc Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 27 Jan 2021 21:46:19 -0700 Subject: [PATCH] Test strvec_join() using strlcpy_unesc(). Emulates an overflow like: sudoedit -s '\' `perl -e 'print "A" x 65536'` --- plugins/sudoers/Makefile.in | 2 +- .../sudoers/regress/unescape/check_unesc.c | 62 +++++++++++++++++-- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 5a7c92f69..36743ff36 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -230,7 +230,7 @@ CHECK_SYMBOLS_OBJS = check_symbols.o CHECK_STARTTIME_OBJS = check_starttime.o starttime.lo sudoers_debug.lo -CHECK_UNESC_OBJS = check_unesc.o strlcpy_unesc.lo sudoers_debug.lo +CHECK_UNESC_OBJS = check_unesc.o strlcpy_unesc.lo strvec_join.lo sudoers_debug.lo VERSION = @PACKAGE_VERSION@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ diff --git a/plugins/sudoers/regress/unescape/check_unesc.c b/plugins/sudoers/regress/unescape/check_unesc.c index b955eaaee..4035e70de 100644 --- a/plugins/sudoers/regress/unescape/check_unesc.c +++ b/plugins/sudoers/regress/unescape/check_unesc.c @@ -45,16 +45,15 @@ struct test_data { sudo_dso_public int main(int argc, char *argv[]); -int -main(int argc, char *argv[]) +static void +test_strlcpy_unescape(int *ntests_out, int *errors_out) { - int ntests = 0, errors = 0; + int ntests = *ntests_out; + int errors = *errors_out; struct test_data *td; char buf[1024]; size_t len; - initprogname(argc > 0 ? argv[0] : "check_unesc"); - for (td = test_data; td->input != NULL; td++) { ntests++; memset(buf, 'A', sizeof(buf)); @@ -82,6 +81,59 @@ main(int argc, char *argv[]) } } + *ntests_out = ntests; + *errors_out = errors; +} + +static void +test_strvec_join(int *ntests_out, int *errors_out) +{ + int ntests = *ntests_out; + int errors = *errors_out; + char buf[64*1024 + 1], expected[64*1024 + 3]; + char *argv[3], *result; + + /* Test joining an argument vector while unescaping. */ + memset(buf, 'A', sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + argv[0] = "\\"; + argv[1] = buf; + argv[2] = NULL; + + memset(expected, 'A', sizeof(expected)); + expected[0] = '\\'; + expected[1] = ' '; + expected[sizeof(expected) - 1] = '\0'; + + ntests++; + result = strvec_join(argv, ' ', strlcpy_unescape); + if (result == NULL) { + sudo_warnx("%d: failed to join argument vector", ntests); + errors++; + } else if (strcmp(result, expected) != 0) { + sudo_warnx("%d: got \"%s\", expected \"%s\"", ntests, + result, expected); + errors++; + } + free(result); + + *ntests_out = ntests; + *errors_out = errors; +} + +int +main(int argc, char *argv[]) +{ + int ntests = 0, errors = 0; + + initprogname(argc > 0 ? argv[0] : "check_unesc"); + + /* strlcpy_unescape tests */ + test_strlcpy_unescape(&ntests, &errors); + + /* strvec_join test */ + test_strvec_join(&ntests, &errors); + printf("%s: %d tests run, %d errors, %d%% success rate\n", getprogname(), ntests, errors, (ntests - errors) * 100 / ntests);