wprintf: %p with NULL pointer
Asked Answered
F

2

7

As I was writing a unit test, I stumbled upon some odd behavior from glibc, regarding "%p" and the NULL pointer.

If I have a line such as printf("NULL pointer is %p\n", NULL);, then I see NULL pointer is (nil) printed to the screen, as I expected.

If I instead use the wide-character version: wprintf(L"NULL pointer is %p\n", NULL);, then it prints out NULL pointer is (, and stops at the opening parenthesis. If I print a non-NULL pointer, it prints that pointer, both normal and wide-character versions. Is this a known bug of glibc, or am I just missing something?

NB: I realize that the C standard says that pointers with %p are converted in an implementation-defined manner; it just seems unusual to just print ( for a NULL pointer.

Find answered 28/7, 2014 at 18:48 Comment(7)
looks like a bug .....Bantling
The result strings do not match what one would expect from the format strings: in the format strings, there are single quote marks (') around the %p, but they do not appear in the result strings. Is this a typo in the question?Stomatitis
Instead of NULL, have you tried L'\0'?Trifling
@FiddlingBits %p expects a pointer, whereas L'\0' is an integer constant. Regardless, it still gives the same result.Find
This can't be right either...Identic
@Identic that's because you can't mix printf and wprintf on the same stream - once a stream is oriented as either wide character or not, it can't be changedFind
@Drew First time I noticed this. Then again, I never mixed wide and non-wide output. Nice answer on the matter (including comments).Identic
S
8

This is definitely a bug: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=stdio-common/vfprintf.c;hb=c15cf13a8a672bd27bf3d94b995c52872eed537d#l932

 934             /* Write "(nil)" for a nil pointer.  */                           \
 935             string = (CHAR_T *) L_("(nil)");                                  \
 936             /* Make sure the full string "(nil)" is printed.  */              \
 937             if (prec < 5)                                                     \
 938               prec = 5;                                                       \
 939             is_long = 0;        /* This is no wide-char string.  */           \
 940             goto LABEL (print_string);                                        \

The L_("(nil)") expands to L"(nil)" for wprintf, but a couple of lines later is_long is set to 0 (i.e. false). As a result string is interpreted as a narrow-character string, so printing it will stop at its first zero byte i.e. after the (.

Reported bug link: https://sourceware.org/bugzilla/show_bug.cgi?id=16890 - this is fixed in version 2.20 of glibc.

Interestingly, this bug appears to have existed for almost 15 years before it was found and fixed - within 2 days of its reporting!

Sportswoman answered 28/7, 2014 at 19:7 Comment(0)
H
1

Confirmed on Ubuntu 14.04 LTS; GNU C Library (Ubuntu EGLIBC 2.19-0ubuntu6).

It seems to be a reported bug in at least Debian glibc; the bug has been fixed on 1 May 2014, and should be available in Glibc 2.20. Just wait for upstream updates.

Hampson answered 28/7, 2014 at 19:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.