gct
gct

Reputation: 14583

How to count number of arguments to a format string in C?

I've got a program that takes a format string from the command line which represents the format for the filenames of multiple output files. It should take just a single integer argument that can be substituted in to generate the real output filenames, and I'd like to verify that when doing my input checking. What's a good way to determine the number of arguments a format string expects in C?

Upvotes: 1

Views: 1153

Answers (2)

jg6
jg6

Reputation: 316

The GNU C library contains a function parse_printf_format that can be used in your case. From the glibc manual, section 12.12.10 - Parsing a template string:

You can use the function parse_printf_format to obtain information about the number and types of arguments that are expected by a given template string. This function permits interpreters that provide interfaces to printf to avoid passing along invalid arguments from the user’s program, which could cause a crash.

parse_printf_format returns the total number of arguments required by template. If this number is greater than n, then the information returned describes only the first n arguments. If you want information about additional arguments, allocate a bigger array and call parse_printf_format again.

Usecase example:

#include <printf.h>
size_t arguments_count = parse_printf_format ("Your discount: %d%%\n", 0, NULL);
/* arguments_count now holds a value of 1 */

Upvotes: 1

ecatmur
ecatmur

Reputation: 157394

The number of arguments accepted depends on the version of your C library (for example, %a conversion specifiers were added in C99). You can be certain that it is no greater than the number of unescaped % characters (i.e., the number of % characters remaining after all %% sequences are removed) plus the number of * characters (which could be width specifiers).

You should consider security issues, though; if the user supplies a %n format specifier this could result in a write to an arbitrary memory location. In other cases, supplying e.g. %f would result in garbage values being output, %s in arbitrary memory contents, and even with %d specifiers allowing the user to supply a field width e.g. %255d could result in buffer overflow. It would be smarter to consider a different formatting scheme e.g. replacing a token (which could still be %d), but not allowing the user to supply a printf format string.

Upvotes: 1

Related Questions