/* format string test program * by team teso * */ #define VERSION "0.0.1" #include #include #include #include #include void test_has_n (void); void test_has_star (void); void test_has_nstar (void); void test_has_star_ow (void); void test_has_dollar (void); void test_has_float (void); void test_has_dot_float (void); void test_size_snprintf (void); void test_size_snprintf_NUL (void); void test_size_non_write_count (void); typedef struct { char * test_name; char * description; void (* func)(void); } testent; testent tests[] = { { "has_n", "determines whether %n is possible", test_has_n }, { "has_star", "determines whether stars within integer prints " "are possible", test_has_star }, { "has_nstar", "determines whether multiple stars can be used at " "once", test_has_nstar }, { "has_star_ow", "determines whether this implementation allows " "to overwrite\n the size specified " "with a star directive later on", test_has_star_ow }, { "has_dollar", "determines whether this implementation allows " "the $-sign\n to specify the length " "parameter", test_has_dollar }, { "has_float", "determines whether %f is possible", test_has_float }, { "has_dot_float", "determines whether %.f is possible", test_has_dot_float }, { "size_snprintf", "the size in bytes that %n writes", test_size_snprintf }, { "size_non_write_counts", "a large write, which exceeds the buffer " "size counts to the\n written counter " "anyway", test_size_non_write_count }, { NULL, NULL, NULL }, }; char buffer[1024]; /* for tests to use and populate freely */ void test_has_n (void) { int i = 0; sprintf (buffer, "aaa%n", &i); printf ("has_n %s\n", i == 3 ? "yes" : "no"); } void test_has_star (void) { sprintf (buffer, "%*d", 30, 7350); printf ("has_star %s\n", strlen (buffer) == 30 ? "yes" : "no"); } void test_has_nstar (void) { sprintf (buffer, "%**d", 50, 30, 7350); printf ("has_nstar %s\n", strlen (buffer) == 30 ? "yes" : "no"); } void test_has_star_ow (void) { sprintf (buffer, "%*10d", 30, 1); printf ("has_star_ow %s\n", strlen (buffer) == 10 ? "yes" : "no"); } void test_has_dollar (void) { sprintf (buffer, "%2$d", 1, 30); printf ("has_dollar %s\n", strcmp (buffer, "30") == 0 ? "yes" : "no"); } void test_has_float (void) { float f = 3.14; sprintf (buffer, "%f", f); printf ("has_float %s\n", memcmp (buffer, "3.14", 4) == 0 ? "yes" : "no"); } void test_has_dot_float (void) { float f = 3.14; sprintf (buffer, "%.f", f); printf ("has_dot_float %s\n", strcmp (buffer, "3") == 0 ? "yes" : "no"); } void test_size_snprintf (void) { char buf[5]; memset (buf, '\x00', sizeof (buf)); buf[4] = 'a'; snprintf (buf, sizeof (buf) - 1, "abcd"); if (buf[3] == 'd' && buf[4] == 'a') { printf ("size_snprintf weak_adjascent\n"); } else if (buf[3] == 'd' && buf[4] == '\x00') { printf ("size_snprintf weak_NUL_store\n"); } else if (buf[2] == 'c' && buf[3] == '\x00') { printf ("size_snprintf ok\n"); } } void test_size_non_write_count (void) { int i = 0; char buf[256]; /* work around a bug in libc here */ snprintf (buf, sizeof (buf), "%500d%n", 10, &i); printf ("size_non_write_count %s\n", i > 256 ? "exceeds" : "remains"); } int main (int argc, char *argv[]) { int i; if (argc != 2) { printf ("format string test program version "VERSION"\n" "by team teso\n\n"); printf ("usage: %s \n\n", argv[0]); for (i = 0 ; tests[i].test_name != NULL ; ++i) { printf ("%-22s %s\n", tests[i].test_name, tests[i].description); } exit (EXIT_SUCCESS); } memset (buffer, '\x00', sizeof (buffer)); for (i = 0 ; tests[i].test_name != NULL ; ++i) { if (strcmp (tests[i].test_name, argv[1]) == 0) tests[i].func (); } exit (EXIT_SUCCESS); }