Examples:
"Something %d" and "Something else %d" // Compatible
"Something %d" and "Something else %f" // Not Compatible
"Something %d" and "Something %d else %d" // Not Compatible
"Something %d and %f" and "Something %2$f and %1$d" // Compatible
I figured there should be some C function for this, but I'm not getting any relevant search results. I mean the compiler is checking that the format string and the arguments match, so the code for checking this is already written. The only question is how I can call it.
I'm using Objective-C, so if there is an Objective-C specific solution that's fine too.
My understanding of what you want, is that, you basically want a method which can look at two strings and detect if they both have the same types of values in them. Or something a long those lines.... If so, then try this (or something along the lines of this):
Checking if 2
printf()
format strings are compatible is an exercise in format parsing.C, at least, has no standard run-time compare function such as:
Formats like
"%d %f"
and"%i %e"
are obviously compatible in that both expect anint
andfloat/double
. Note:float
are promoted todouble
asshort
andsigned char
are promoted toint
.Formats
"%*.*f"
and"%i %d %e"
are compatible, but not obvious: both expect anint
,int
andfloat/double
.Formats
"%hhd"
and"%d"
both expect anint
, even though the first will have it values cast tosigned char
before printing.Formats
"%d"
and"%u"
are not compatible. Even though many systems will behaved as hoped. Note: Typicallychar
will promote toint
.Formats
"%d"
and"%ld"
are not strictly compatible. On a 32-bit system there are equivalent, but not in general. Of course code can be altered to accommodate this. OTOH"%lf"
and"%f"
are compatible due to the usual argument promotions offloat
todouble
.Formats
"%lu"
and"zu"
may be compatible, but that depends on the implementation ofunsigned long
andsize_t
. Additions to code could allow this or related equivalences.Some combinations of modifiers and specifiers are not defined like
"zp"
. The following does not dis-allow such esoteric combinations - but does compare them.Modifiers like
"$"
are extensions to standard C and are not implemented in the following.The compatibility test for
printf()
differs fromscanf()
.Note: only minimal testing done. Lots of additional considerations could be added.
Known shortcomings:
hh,h,l,ll,j,z,t
modifiers withn
.l
withs,c
.[Edit]
OP comments about security concerns. This changes the nature of the post and the compare from an equality one to a security one. I'd imagine that one of the patterns (A) would be a reference pattern and the next (B) would be the test. The test would be "is B at least as secure as A?". Example
A = "%.20s"
andB1 = "%.19s"
,B2 = "%.20s"
,B3 = "%.21s"
.B1
andB2
both pass the security test as they do not extract more the 20char
.B3
is a problem as it goes pass the reference limit of 20char
. Further any non-width qualified with%s %[ %c
is a security problem - in the reference or test pattern. This answer's code does not address this issue.As mentioned, code does not yet handle modifiers with
"%n"
.[2018 edit]
Concerning "Formats
"%d"
and"%u"
are not compatible.": This is for values to be printed in general. For values in the[0..INT_MAX]
range, either format may work per C11dr §6.5.2.2 6.