Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printf a buffer with nulls

Tags:

c++

c

printf

packet

Is there some fancy printf syntax to ignore nulls when printing a string?

Example use case: printing a network packet that contains a bunch of null terminated strings.

My test code to illustrate the issue:

#include <cstdio>
#include <cstring>

void main()
{
    char buffer[32];
    const char h[] = "hello";
    const char w[] = "world";
    const int size = sizeof(w) + sizeof(h);

    memcpy(buffer, h, sizeof(h));
    memcpy(buffer + sizeof(h), w, sizeof(w));

    //try printing stuff with printf
    printf("prints only 'hello' [%s]\n",buffer);
    printf("this prints '<bunch of spaces> hello' [%*s]\n",size,buffer);
    printf("and this prints 'hello' [%.*s]\n",size,buffer);

    //hack fixup code
    for(int i = 0; i < size; ++i)
    {
        if(buffer[i] == 0)
            buffer[i] = ' ';
    }
    printf("this prints 'hello world ' [%.*s]\n",size,buffer);
}
like image 648
Chad Avatar asked Jul 14 '26 19:07

Chad


2 Answers

printf assumes strings are c-style (i.e. ending in null characters). You need to do one of the following:

1) use the write method of ostream (C++ style)

2) use the write command (from unistd.h, C style)

3) iterate through each character and print.

When I am debugging packets, oftentimes I will print out each character using the %02hhx format to be sure I see the exact code (without any quirks about printing null characters to the screen)

like image 169
Foo Bah Avatar answered Jul 17 '26 16:07

Foo Bah


There isn't a way to tell printf the length of the string you want to print. You'll need to print each character individually:

void printbuf(const char* buffer, int len) {
    for (int i = 0; i < len; ++i)
        printf("%c", buffer[i]);
}

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
printbuf(buf, 7);

// prints
// abc abc

You could wrap the buffer in a string and print that (if you don't mind the duplication), since NULLs do not delimit strings:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};

string strwithnulls(buf, buf + 7); // or as John pointed out, string strwithnulls(buf, 7);
cout << strwithnulls;

// prints
// abc abc

But better yet

you could use write of std::ostream, because you are using C++ after all:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
cout.write(buf, 7); // best yet

If you are actually using C (why'd you tag it C++?) you can do this:

char buf[] = {'a', 'b', 'c', 0, 'a', 'b', 'c'};
fwrite(buf, 1, 7, stdout);
like image 35
Seth Carnegie Avatar answered Jul 17 '26 16:07

Seth Carnegie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!