++num_fmt;
+ bool suppress_assignment = false;
+ if (fmt == '*') {
+ fmt = *++c;
+ suppress_assignment = true;
+ }
+
/* look for length modifiers */
format_length_modifier_t fmt_mod = FMT_MOD_NONE;
switch (fmt) {
break;
case 'c':
- expected_type = type_int;
switch (fmt_mod) {
case FMT_MOD_NONE: expected_type = type_char; break;
case FMT_MOD_l: expected_type = type_wchar_t; break;
expected_type = type_void_ptr;
break;
- case 'n':
+ case 'n': {
+ if (suppress_assignment) {
+ warningf(WARN_FORMAT, pos, "conversion '%n' cannot be suppressed with '*' at format %u", num_fmt);
+ }
+
switch (fmt_mod) {
case FMT_MOD_NONE: expected_type = type_int; break;
case FMT_MOD_hh: expected_type = type_signed_char; break;
goto next_arg;
}
break;
+ }
default:
warningf(WARN_FORMAT, pos, "encountered unknown conversion specifier '%%%c' at format %u", fmt, num_fmt);
+ if (suppress_assignment)
+ continue;
if (arg == NULL)
goto too_few_args;
goto next_arg;
}
+ if (suppress_assignment)
+ continue;
+
if (arg == NULL) {
too_few_args:
warningf(WARN_FORMAT, pos, "too few arguments for format string");