/* chksnprintf.c */ /* Copyright 1998, 1999 by Eberhard Mattes Donated to the public domain. No warranty. 1998-09-03 Initial version 1999-01-01 #include "firewall.h" */ #include #include #include #include #include "firewall.h" /* DONT_HAVE_VSNPRINTF */ #include "libemfw.h" /* Call check_snprintf() to check if snprintf() and vsnprintf() really restrict the output to the limit passed as argument. Rather than creating a separate program for checking snprintf() and vsnprintf(), this function should be called from the application, to make sure that linking options and libraries (libdb on Linux!) don't affect the result. */ static int warning; #ifndef DONT_HAVE_VSNPRINTF static char buf[1024]; static void fix (void) { puts ("Please add the line\n"); puts (" #define DONT_HAVE_VSNPRINTF\n"); puts ("to firewall.h, run \"make clean\" in all relevant directories,"); puts ("and rebuild."); exit (2); } static void fail (int n) { printf ("\nYour snprintf() and/or vsnprintf() functions are broken, " "case %d.\n\n", n); fix (); } void test1 (void) { int n; memset (buf, 'x', sizeof (buf)); n = snprintf (buf, 5, "%.23s", "abcdefghijklmnopqrstuvwxyz"); if (n == -1) warning = 1; else if (n != 23) fail (1); if (memcmp (buf, "abcd\000xxxx", 9) != 0) fail (2); memset (buf, 'x', sizeof (buf)); n = snprintf (buf, 2, "%ld", 98765432L); if (n == -1) warning = 1; else if (n != 8) fail (3); if (memcmp (buf, "9\000xxxx", 6) != 0) fail (4); } void test2 (size_t limit, int nexp, const char *sexp, size_t sexplen, int casenum, const char *fmt, ...) { int n; va_list arg_ptr; memset (buf, 'x', sizeof (buf)); va_start (arg_ptr, fmt); n = vsnprintf (buf, limit, fmt, arg_ptr); if (n == -1) warning = 1; else if (n != nexp) fail (casenum+0); if (memcmp (buf, sexp, sexplen) != 0) fail (casenum+1); } #endif void check_snprintf (int level) { #ifndef DONT_HAVE_VSNPRINTF test1 (); test2 (5, 23, "abcd\000xxxx", 9, 5, "%.23s", "abcdefghijklmnopqrstuvwxyz"); test2 (2, 8, "9\000xxxx", 6, 7, "%ld", 98765432L); if (warning) { puts ("\nThe return value of this system's snprintf() and/or " "vsnprintf() functions"); fputs ("is incorrect", stdout); if (level >= 1) { puts (".\n"); fix (); } else puts (", but that doesn't preclude their usage in this program.\n"); } #else warning = level; /* Keep the compiler happy */ #endif }