简体   繁体   中英

Compatibility of vsnprintf and the macros from inttypes

I'm rewriting some code to be compatible with 32-bit and 64-bit architectures, and I'm having trouble with a vsnprintf call. It doesn't appear that vsnprintf handles the fixed size integer types from inttypes.h properly on either architecture.

Here is the relevant code:

void formatString(char *buffer, int size, char *format, ...)
{
    va_list va;

    /* Format the data */
    va_start( va, format );
    vsnprintf( (char *)buffer, size, format, va );
    va_end( va );
}

int main(int argc, char *argv[])
{
    char buffer[2048];

    printf("The format string: %s\n", stringsLookup(0));
    formatString(&buffer[0], sizeof(buffer), stringsLookup(0), 1, 2);
    printf("The output string: %s\n", buffer);

    return 0;
}

The output is as follows:

The format string: action=DoSomething&Val1=%"PRIx32"&Val2=%x
The output string: action=DoSomething&Val1=%"PRIx32"&Val2=1

You can see that the %"PRIx32" portion of the format string was not replaced with the value '1' as expected. Is this a known issue? Is there a work around?

I will mention that if I hard code the strings in the source, the preprocessor appears to convert "%PRIu32" to the appropriate macro for the architecture and the call to vsnprintf works. Unfortunately I need to be able to load the strings.

Update

Some additional background: When I moved from a 32-bit system to a 64-bit system, I had to fix the size of certain variables. I declared them as uint32_t. I also changed the places where they were printed to clean up compiler warnings. The previous code used printf("%lx") . I used printf("%"PRIx32) . I need to do something similar with the call to vsnprintf.

As I've mentioned, if I hard code the string in the source code, the preprocessor appears to convert "%"PRIx32 to "%lx" or "%x" appropriately. Unfortunately, I'm running into trouble when I have to load the strings from a file. The preprocessor can't help me there.

PRIx32 is a macro whose name should not appear textually even in the format string. You are almost certainly using it wrong, unless it expands to a string that contains "PRIx32" (it almost certainly doesn't).

A typical use is printf("Number: %" PRIx32 "...", arg); .

In the typical idiom above, "Number: %" PRIx32 "..." is expanded to, say, "Number: %" "lX" "..." , which by a peculiarity of C syntax is equivalent to "Number: %lX..."

If you need to create the format string dynamically, use strcat or other string-manipulation functions. Do not write the equivalent of "Number: %\\"PRIx32\\"..." .

Just remember that PRIx32 expands to a string literal, and don't write "%PRIx32" , that does not make sense.

EDIT:

If you are loading the format string from a file, information that I suggested you provide in a comment 45 minutes ago, then you have to do your own substitution when the file is loaded from. Invent a syntax similar to the % syntax of printf, and write your own function to recognize it and substitute it with what is right on the architecture the program is running on.

Note that from a security point of view, if you load format strings from a file, whoever controls the file controls what the program does .

Also note that printf("Number: %llx\\n", (unsigned long long) e); almost always work. It can only disappoint you if your compiler has an integer type wider than unsigned long long and you use it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM