Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing null pointer to printf

104 views
Skip to first unread message

n...@bcbsil.com

unread,
Oct 28, 1997, 3:00:00 AM10/28/97
to

I'm trying to port some C programs over to a Solaris 2.5 system using
SPARCompiler C 4.0. Apparently on the old setup (a SunOS 4.1.3 system),
passing a null pointer to printf as a string, e.g.:

printf("Kiss my %s!\n", (char *) 0);

would be sorta O.K. (It results in "Kiss my (null)!" being printed.)
However, with the new setup, it results in a segmentation fault (ouch).

- Is this what it's supposed to do?
- How can I correct for this without changing my code?

Thanks in advance for any help!

-------------------==== Posted via Deja News ====-----------------------
http://www.dejanews.com/ Search, Read, Post to Usenet

Peter Seebach

unread,
Oct 28, 1997, 3:00:00 AM10/28/97
to

In article <8780768...@dejanews.com>, <n...@bcbsil.com> wrote:
>I'm trying to port some C programs over to a Solaris 2.5 system using
>SPARCompiler C 4.0. Apparently on the old setup (a SunOS 4.1.3 system),
>passing a null pointer to printf as a string, e.g.:

>printf("Kiss my %s!\n", (char *) 0);

>would be sorta O.K. (It results in "Kiss my (null)!" being printed.)
>However, with the new setup, it results in a segmentation fault (ouch).

>- Is this what it's supposed to do?

Sure! Anything is peachy keen. %s takes a string. A null pointer
is not a string. You have, by calling printf(), promised to pass
it valid arguments. You break promises, the compiler breaks your
face.

>- How can I correct for this without changing my code?

You can't. You will need to fix the code. This shouldn't be hard; you
can always use
s ? s : "(null)"

-s
--
se...@plethora.net -- Speaking for myself. No spam please.
Copyright 1997. All rights reserved. This was not written by my cat.
C/Unix wizard - send mail for help! -- <URL:http://www.plethora.net/~seebs>
<URL:http://www.plethora.net/> - More Net, Less Spam!

Lawrence Kirby

unread,
Oct 28, 1997, 3:00:00 AM10/28/97
to

>I'm trying to port some C programs over to a Solaris 2.5 system using
>SPARCompiler C 4.0. Apparently on the old setup (a SunOS 4.1.3 system),
>passing a null pointer to printf as a string, e.g.:
>
>printf("Kiss my %s!\n", (char *) 0);
>
>would be sorta O.K. (It results in "Kiss my (null)!" being printed.)
>However, with the new setup, it results in a segmentation fault (ouch).
>
>- Is this what it's supposed to do?

The printf %s conversion specifier requires an argument that is a pointer
to a string. A null pointer doesn't qualify - passing a null pointer
results in undefined behaviour which means that there are no constraints
on what the compiler and code might do - anything they do is correct
including a segmentation fault.

>- How can I correct for this without changing my code?

Don't try - fix the buggy code.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------


Morris M. Keesan

unread,
Oct 28, 1997, 3:00:00 AM10/28/97
to

On Tue, 28 Oct 1997 16:40:41 -0600, n...@bcbsil.com wrote:
>I'm trying to port some C programs over to a Solaris 2.5 system using
>SPARCompiler C 4.0. Apparently on the old setup (a SunOS 4.1.3 system),
>passing a null pointer to printf as a string, e.g.:
>
>printf("Kiss my %s!\n", (char *) 0);
>
>would be sorta O.K. (It results in "Kiss my (null)!" being printed.)
>However, with the new setup, it results in a segmentation fault (ouch).
>
>- Is this what it's supposed to do?
>- How can I correct for this without changing my code?

The behavior in this case is undefined, so the implementation is free to
do whatever it pleases. (ANSI standard, 7.9.6.1: The argument shall be
a pointer to an array of character type; and G.2 "The behavior in the
following circumstances is undefined: ... A ... null pointer reference
. occurs").

Your code is broken. The only way you can correct this without fixing
this bug in your code would be to write your own version of printf.
--
Morris M. Keesan -- mke...@kenan.com
Kenan Systems Corporation

n...@bcbsil.com

unread,
Oct 29, 1997, 3:00:00 AM10/29/97
to

Thanks to everyone for their help here and in e-mail. However, maybe I
wasn't clear on my second question. It is easy enough to change the
code, but how would one handle the general case, i.e. how can I ensure
that there are no printf (or fprintf, etc.) statements that might be
passed a null pointer? I can't do a global replacement, since there the
variables involved would be different in most cases. I suppose I can
write a macro replacement for the printf function that does checking...
But I guess I was really looking for some sort of option that might
toggle this behavior with the old behavior. Perhaps I should post this
on the Solaris groups.

-- Roy

Peter Seebach

unread,
Oct 29, 1997, 3:00:00 AM10/29/97
to

In article <8781511...@dejanews.com>, <n...@bcbsil.com> wrote:
>Thanks to everyone for their help here and in e-mail. However, maybe I
>wasn't clear on my second question. It is easy enough to change the
>code, but how would one handle the general case, i.e. how can I ensure
>that there are no printf (or fprintf, etc.) statements that might be
>passed a null pointer? I can't do a global replacement, since there the
>variables involved would be different in most cases. I suppose I can
>write a macro replacement for the printf function that does checking...
>But I guess I was really looking for some sort of option that might
>toggle this behavior with the old behavior. Perhaps I should post this
>on the Solaris groups.

Well, the best you can probably do is to find every occurance of
printf that takes either some kind of %s argument (remember, this
could be '%*.*s', '%23.2s', or something like hat), or some kind
of %n argument. Then, follow all of the logic that leads to them,
or surround them with tests.

This is not *nearly* as bad as it sounds; in fact, a good lint may
be able to do it.

Remember, anything other than a string literal as a format string
needs to be checked, in case it's ever a format including a %s,
etc etc.

A code coverage tool may also help you, but may not be sufficient.

I am not aware of any options to toggle the behavior, although you
*might* get somewhere by using the "ucb" C compiler - however, the
SVR4 ucb library is *VERY* buggy, and even if it's a cure, it's
worse than the disease.

Alicia Carla Longstreet

unread,
Oct 29, 1997, 3:00:00 AM10/29/97
to n...@bcbsil.com

n...@bcbsil.com wrote:

> Thanks to everyone for their help here and in e-mail. However, maybe I
> wasn't clear on my second question. It is easy enough to change the
> code, but how would one handle the general case, i.e. how can I ensure
> that there are no printf (or fprintf, etc.) statements that might be
> passed a null pointer? I can't do a global replacement, since there the
> variables involved would be different in most cases. I suppose I can
> write a macro replacement for the printf function that does checking...
> But I guess I was really looking for some sort of option that might
> toggle this behavior with the old behavior. Perhaps I should post this
> on the Solaris groups.

That might be a good idea.
You cannot portably solve your problem. Although there may be several
possiblities for doing it non-portably.

1) It is possible that your compiler already has a consistant method of
handling this. It is undefined behavior in terms of The Standard but
that does not mean that your compiler does not provide an out. Check
your compiler documentation. (One of my compilers does in fact print
"(null)" if I inadvertantly pass it a NULL pointer as a pointer to char.

2) If you have the source code for your compilers printf() (sorry seebs
;-)) you can always alter the code and recompile (recommend you keep it
out of the library, old chap, just make sure that the linker will select
*your* version over the *real* version), this is *NOT* portable and in
fact may not work at all (some implementation allow the compile to
inline code from standard functions or have the code in something other
than a traditional library). Note, upgrading to a new compiler will
require that you do this all over again.

3) You could write a wrapper function or a new function for printf()
that checks all the values passed for a NULL char* (call it myprintf()
or something), then replace every call to printf() with a call to you
new function. Either use the source to printf() (see above) with a
different name and a built-in check or create a wrapper that checks any
char* arguments and if none simply calls printf() with the original
values, otherwise substitues valid values for the bad ones. (seebs will
like this *much* better). Note, upgrading to a new compiler will
require that you do this all over again.

4) (*BEST*) You could always go through and correct all your code (by
hand, sorry, although a global search will find all of your printf()'s).

--
Isn't it a bit unnerving that doctors call what they do "practice"?
Why do they report power outages on TV?
Why do people who know the least know it the loudest?
If vegetarians eat vegetables, what do humanitarians eat?
From the Zen of George Carlin.
=========================================
Alicia Carla Longstreet ca...@ici.net
=========================================
READ THE FAQ for more information:
C-FAQ ftp sites: ftp://ftp.eskimo.com or ftp://rtfm.mit.edu
Hypertext C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html

Stephan Wilms

unread,
Oct 30, 1997, 3:00:00 AM10/30/97
to

n...@bcbsil.com wrote:
>
> Thanks to everyone for their help here and in e-mail. However, maybe I
> wasn't clear on my second question. It is easy enough to change the
> code, but how would one handle the general case, i.e. how can I ensure
> that there are no printf (or fprintf, etc.) statements that might be
> passed a null pointer? I can't do a global replacement, since there the
> variables involved would be different in most cases. I suppose I can
> write a macro replacement for the printf function that does checking...

Hi n...@bcbsil.com,

You want some help fom your compiler, without having to change the
code at all, or maybe with only very minor changes. That is only
possible if you can find a compiler that meets your requirements.

To do it in a portable way, so that your code will perform as expected
on *any* copmpiler it is ported to, requires you to do a lot more
work. The safest way is to write your own version of the "printf()"
(and related) function(s) and demand that everyone calls only this
function, eg. "my_printf()". Now you have full control over what
is printed in which way. Internally you can use the "vprintf()"
function to do the main work.

Stephan
(initiator of the campaign against grumpiness in c.l.c)

Douglas A. Gwyn

unread,
Nov 2, 1997, 3:00:00 AM11/2/97
to

In article <638bp7$903$2...@darla.visi.com>,

se...@plethora.net (Peter Seebach) wrote:
>Well, the best you can probably do is to find every occurance of
>printf that takes either some kind of %s argument (remember, this
>could be '%*.*s', '%23.2s', or something like [t]hat), or some kind
>of %n argument.

If his text editor supports regular expressions, as do "ed", "vi",
"emacs", and "sam", among others, then searching for a pattern like
%[^a-mo-rt-z%]*[ns]
should find nearly all of them.

>Then, follow all of the logic that leads to them,
>or surround them with tests.

Here is a general fix, although not as nice as fixing the code logic:
printf("...%s...",...,expr,...);
->
printf("...%s...",...,(expr)?(expr):"(null)",...);
(I know, there are some details such as dealing with side effects.
Anybody with code like that deserves to do some extra work!)


Douglas A. Gwyn

unread,
Nov 5, 1997, 3:00:00 AM11/5/97
to

In article <34566c80.116430984@news>,

mke...@kenan.com (Morris M. Keesan) wrote:
>Your code is broken. The only way you can correct this without fixing
>this bug in your code would be to write your own version of printf.

Even that might not help -- there is no guarantee that one can supply
one's own replacement for a standard library function. The library
may have internal mechanisms of which the programmer is unaware, so
things could break in various horrible ways if you circumvent parts
of the library (which is designed to work as an integrated whole).

When you do try this approach, you should name your own function
something different from the standard library function, e.g. myprintf.


0 new messages