hexump.c

N

Nobody

Do you know of an existing system that doesn't set argv[0] to the name
of the program?

ANY EXAMPLE?

Yes. Every Unix system in existence, as has already been pointed out.

The *system* doesn't set argv[0] to the name of the program. Individual
programs may do this, or they may not.

As a (slight) counter-example, "login" invokes the user's shell with
argv[0] set to the name of the program but with a "-" in front of it (e.g.
"-bash"). By convention, if (argv[0][0] == '-') then the shell is being
invoked as a "login shell", so it should read some combination of
~/.login, ~/.profile, /etc/profile and/or similar implementation-specific
files. Non-login shells don't do this (so that sub-shells inherit the
existing environment, rather than having it reset to its initial state).
 
J

John Bode

[snip]
But consider this: students who learned to program on a PDP-11 or a VAX
are probably no longer using those systems.  Students learning today on
a Windows, Linux, or Macintosh system may be using very different
systems in the future.  It's never too early to learn good habits.

I learned the value of this early on, even though I didn't realize it
at the time. I was one of those students learning on a VAX, and I
made the mistake of buying the first edition of Schildt, which assumed
you were working on DOS. Most of the examples didn't even compile
because they relied on MS-specific extensions and headers.

For me, that book was largely useless and a waste of money, especially
when compared with K&R or H&S, which made no such platform-specific
assumptions.

As it was, we were taught pretty vanilla C for our assignments; if we
played with any of the VAX C-specific extensions, it was for our own
abusement more than anything else.
 
J

jacob navia

Le 15/09/11 00:31, John Bode a écrit :
Or he may just be a jackass.

Then, those hypocrites say:

WHY ( oh WHY) this guy is SO PARANOIC!

I never insulted him, we are all so KIND with him and HE treat us so
BADLY

You aren't even an insult worth Mr Bode.
 
K

Kleuskes & Moos

Le 15/09/11 00:31, John Bode a écrit :

Then, those hypocrites say:

WHY ( oh WHY) this guy is SO PARANOIC!

I never insulted him, we are all so KIND with him and HE treat us so
BADLY

You aren't even an insult worth Mr Bode.

If someone says you *may* be a jackass, why do you feel the need to
prove that hypothesis?

I'm just being curious, since it seems to be counterproductive.

-------------------------------------------------------------------------------
______
< Yow! >
------
\
\
___
{~._.~}
( Y )
()~*~()
(_)-(_)
-------------------------------------------------------------------------------
 
A

Alan Curry

I've just done this test on several programs. There were many segfaults.
Several print an angry message about argv[0] being NULL and then abort!
It seems to be a "you know exactly what you did and you should be
ashamed of yourself" type of error.

Most disturbing are the many setuid programs that segfaulted, including
passwd, mount, and su.

shells: pdksh, bash, and dash were OK. Others segfaulted.

How many programs did you test? How many segfaulted?

I only picked a few examples of what I thought should be mature utilties with
a low bug count. Maybe about 20.

Here's a larger survey. Most of the versions are from the current Debian
release. The ratio got a little better as I added more, but crashing is still
a very popular option.

Behaves normally:
7zr (9.04~dfsg.1-1)
ar (binutils 2.20.1) [prints help as expected but program name is "(null)"]
as (binutils 2.20.1)
bash (4.1.5(1)-release) [$0 expands to "bash"]
dash (0.5.5.1-7.4) [$0 expands to ""]
false (coreutils 8.5)
gpg (1.4.10)
groff (1.20.1)
pdksh (5.2.14-25) [$0 expands to "pdksh"]
sed (4.2.1) [prints help as expected but program name is "(null)"]
svn (1.6.12)
true (coreutils 8.5)
vim (7.2)
w3m (0.5.2)
xterm (261)

Segfaults and dies immediately:
compress (ncompress 4.2.4.3)
csh (20070713-2)
cvs (1.12.13)
ed (1.4)
gcc (2.95.4, 4.4.5, and others)
git (1.7.2.5)
grep (2.5.1, locally modified)
gzip (1.3.12)
ksh (Version M 93s+ 2008-01-31)
ld (binutils 2.20.1)
less (436)
man (1.5p)
mawk (1.3.3)
more (2.17.2)
mount (2.17.2)
nvi (1.81.6)
passwd (shadow 4.1.4.2+svn3283-2, locally modified)
pax (from an OpenBSD snapshot, I guess? 1:20090728-1)
posh (0.8.5)
su (shadow 4.1.4.2+svn3283-2, locally modified)
tcsh (6.17.02)
xboard (4.4.3)
xz (5.0.0)
zsh (4.3.10)

Segfaults, catches the signal, prints its own substitute for the standard
"Segmentation fault" message:
bzip2 (1.0.5)
gawk (3.1.7)
unzip (6.00)

Complains specifically about argv[0] and aborts:
cat, cp, ln, ls, mv (coreutils 8.5) [and presumably the rest of coreutils]
diff (diffutils 3.0)
tar (1.23)

Miscellaneous weird behavior:
awk (2010-05-23)
says "(null): no program given" (normal behavior with no arguments is to
print a brief usage summary)
nm (binutils 2.20.1)
just exits 0, like /bin/true. (normal behavior with no arguments is to
work on a.out)
perl (5.10.1)
somehow ends up confusing envp with argv, interprets envp[0] as the name
of a script, fails to open it. If I create a perl script with that weird
name, it executes normally, with @ARGV empty and $^X set to the actual
full path to the perl executable.
ping (iputils-sss20100418)
reports that it is pinging hostname "(null)" which has IP address
0.0.0.0, proceeds to ping it successfully (0.0.0.0 works like localhost)
zip (3.0)
if stdout is not a tty, compresses stdin to stdout which is normal
behavior. If stdout is a tty, complains about attempt to compress to
tty instead of printing help which would be normal behavior with no
arguments.
 
K

Keith Thompson

jacob navia said:
Le 14/09/11 21:16, Keith Thompson a écrit :

HYPOCRITE

1. a person who pretends to have virtues, moral or religious beliefs,
principles, etc., that he or she does not actually possess, especially
a person whose actions belie stated beliefs.

2. A person who feigns some desirable or publicly approved attitude,
especially one whose private life, opinions, or statements belie his or
her public statements.

http://dictionary.reference.com/browse/hypocrite

Thank you, I know what the word means. Like most people, I am
probably a hypocrite in some ways (small ones, I hope), but you
are hardly in a position to judge.
Thompson and heathfield rejected the 1999 C standard in countless
posts from 1999 to last year or maybe even today.

That is a lie.

(Well, maybe it's not a deliberate lie. I suppose it's possible
that you actually believe it, but I'm not sure that's better.)

I have pointed out the fact that the C99 standard has not been as
widely adopted as the C90 standard, and offered the advice that
writing code that depends on C99-specific features makes that code
less portable than it would be if it used only C90-specific features.
I have also stated repeatedly that I sincerely wish that C99 had been
more widely adopted. I have fairly consistently said that if 100%
portability is not an issue, then there's nothing wrong with using
C99-specific features; if you can count on having C99-compliant
compilers, go ahead and use them. If you can count on having
compilers that implement enough of C99 for your purposes, that's
fine too. And I have praised you personally for doing your part
by releasing a compiler that seems to implement most or all of the
C99 standard.

I am not a C compiler implementer, so there's very little I can do
to improve the level of support for C99.

I do not advocate avoiding C99 altogether. I advocate being aware of
the implications of the regrettably spotty level of support for it,
and making decisions based on that knowledge.

Incidentally, Richard Heathfield has not posted here in over a year.
Perhaps it's time for you stop obsessing over him.

And the aspects of the standard that you were ignoring, which led
to my comment quoted above, are common to both C90 and C99.
When I posted here code that was conforming to the C99 standard
they would again and again point out that "it is not portable since no
implementations exists", even if many implementation appeared
during all this years. They always again and again said that the only
standard C they accepted was C 1989, the only "portable" C.

They never ( of course) posted any code.

That is a lie. (Maybe; see above.)

I have posted code. It happens that most of what I post here is
answers to questions. Those answers often, but not always, include
code snippets. They sometimes include complete programs, but they
tend to be fairly small. Since you apparently haven't killfiled
me, you must be aware that I do post code. Why would you claim
that I don't? If you're going to lie about someone, you'd be well
advised not to do so in a forum where the proof is easily available.
Of course this doesn't bother them now, since most people that
participated in those discussions have left this group.

Now they start posing with phrases like the one above.

jacob, I have nothing against you personally (or against your
compiler) apart from your obsessive delusion that I am somehow
persecuting you and your repeated unjustifed insults against me.
(I'm not the only target, but I appear to be the primary one
-- along with Richard Heathfield, of course.) I have exercised
extreme patience with you, probably more than I should have, mostly
because you do have some good ideas, you are technically competent,
and you're the author of a C99 compiler. On August 10, I sent you
an e-mail (check your inbox) asking why you treat me as a personal
enemy and asking if we can discuss this like reasonable human beings;
you never responded.

At long last, I have had enough of your crap. I don't know what
your problem is, I don't know what your problem *with me* is, and
I am not qualified either to diagnose it or to help you with it.
I am sick and tired of every technical criticism being treated as
a personal attack, and of of being falsely accused of conspiring
against you.

You recently said, without provocation, that this newsgroup would
be better without me. I'm not going to say that it would be better
without you, but I have little doubt that it will be a more pleasant
place *for me* if you effectively vanish from my view of it.

I am seriously annoyed with you, but I bear you no ill will, and I
wish you the best of luck. I have no advice to offer you because
you surely would not take it.

*plonk*

And the horse you rode in on.
 
K

Keith Thompson

jacob navia said:
Yes. So, you can crash probably most Unix programs that way.
So what?

No, I don't believe you can. It will only crash Unix programs that
don't blindly assume that argv[0] != NULL. If you find Unix programs
that crash when invoked with argv[0] == NULL, you should consider
reporting it as a bug.

I've just done this test on several programs. There were many segfaults.
Several print an angry message about argv[0] being NULL and then abort!
It seems to be a "you know exactly what you did and you should be
ashamed of yourself" type of error.

Most disturbing are the many setuid programs that segfaulted, including
passwd, mount, and su.

shells: pdksh, bash, and dash were OK. Others segfaulted.

That's interesting (and disappointing). I had guessed that,
since execv() can easily invoke any program with argv[0]==NULL,
most production-quality Unix programs would check argv[0] before
dereferencing it. Apparently I was mistaken.

I would argue that these programs *should* check argv[0], even if
they respond by aborting with an error message.

I wonder if there's any real security issue involved here. I suspect
there isn't, but I can't be sure.

[...]
 
K

Keith Thompson

Here's a larger survey. Most of the versions are from the current Debian
release. The ratio got a little better as I added more, but crashing is still
a very popular option.

Behaves normally:
7zr (9.04~dfsg.1-1)
ar (binutils 2.20.1) [prints help as expected but program name is "(null)"]
as (binutils 2.20.1)
bash (4.1.5(1)-release) [$0 expands to "bash"]
dash (0.5.5.1-7.4) [$0 expands to ""]
false (coreutils 8.5)
gpg (1.4.10)
groff (1.20.1)
pdksh (5.2.14-25) [$0 expands to "pdksh"]
sed (4.2.1) [prints help as expected but program name is "(null)"]
svn (1.6.12)
true (coreutils 8.5)
vim (7.2)
w3m (0.5.2)
xterm (261)
[snip]

The ones that print the program name as "(null)" are probably passing a
null pointer to printf or fprintf.
 
B

Ben Pfaff

Keith Thompson said:
That's interesting (and disappointing). I had guessed that,
since execv() can easily invoke any program with argv[0]==NULL,
most production-quality Unix programs would check argv[0] before
dereferencing it. Apparently I was mistaken.

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

Few production-quality Unix programs defend against this, because
it's a *really* unconventional way to invoke a program. No one
(as far as I know) really expects it to be useful to do this.

I think that invoking a program with a null argv[0] is similar,
though perhaps less extreme. It's not a useful or conventional
thing to do, and so there's not much value in checking carefully
for it.

(It could be a security issue for a setuid program. Fortunately
there are few of those and they are usually both simple and
carefully written.)
 
J

Joe Pfeiffer

Ben Pfaff said:
Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

Few production-quality Unix programs defend against this, because
it's a *really* unconventional way to invoke a program. No one
(as far as I know) really expects it to be useful to do this.

I think that invoking a program with a null argv[0] is similar,
though perhaps less extreme. It's not a useful or conventional
thing to do, and so there's not much value in checking carefully
for it.

(It could be a security issue for a setuid program. Fortunately
there are few of those and they are usually both simple and
carefully written.)

You're right that we just assume correct behavior of argv and the file
descriptors. But those are *exactly* the assumptions that turn out to
be exploitable -- I don't think I've ever checked the validity of any of
those (I actually thought execve inserted the program name as argv[0]
until checking the man page a moment ago), but clearly this is a problem
with my programs up until now.

You've got a lot more faith in setuid programs than I do....
 
J

James Kuyper

Keith Thompson said:
That's interesting (and disappointing). I had guessed that,
since execv() can easily invoke any program with argv[0]==NULL,
most production-quality Unix programs would check argv[0] before
dereferencing it. Apparently I was mistaken.

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

I wasn't aware of that option.

There's a key difference here, as far as C is concerned: argc==0 &&
argv[0]==NULL is explicitly permitted by the C standard. Having standard
streams that need to be explicitly opened is not (7.19.3p7).
Few production-quality Unix programs defend against this, because
it's a *really* unconventional way to invoke a program. No one
(as far as I know) really expects it to be useful to do this.

One standard-conforming way to deal with this would be to open() them in
the start-up code that runs before invoking main(). A more subtle
approach would be to have any use of one of the standard streams
automatically open() the appropriate file descriptor, if it has not
already been open()ed, invisibly to the user.
 
N

Nobody

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

Linux traps this for setuid/setgid programs; if any of the standard
descriptors are closed, it open()s /dev/null.
 
J

John Bode

Le 15/09/11 00:31, John Bode a écrit :




Then, those hypocrites say:

WHY ( oh WHY) this guy is SO PARANOIC!

I never insulted him, we are all so KIND with him and HE treat us so
BADLY

You aren't even an insult worth Mr Bode.

Dude, you're the one who told me that I should just piss off and no
longer participate in the group when I mentioned I wasn't writing C
professionally any more. You've been excessively rude to just about
everyone who had an honest disagreement with you.

I don't claim to have never insulted you; I'm the one that called you
a drama queen (a term that I still think fits you the best). I did
that because you were taking criticism over *technical* issues as
personal insults and, well, being overly dramatic about it.

You *invite* this crap.
 
K

Keith Thompson

James Kuyper said:
Keith Thompson said:
That's interesting (and disappointing). I had guessed that,
since execv() can easily invoke any program with argv[0]==NULL,
most production-quality Unix programs would check argv[0] before
dereferencing it. Apparently I was mistaken.

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

I wasn't aware of that option.

There's a key difference here, as far as C is concerned: argc==0 &&
argv[0]==NULL is explicitly permitted by the C standard. Having standard
streams that need to be explicitly opened is not (7.19.3p7).
[...]

Implementations typically can do all sorts of things that violate the
language standard. A debugger can modify the values of objects as
the program is running, which clearly violates the requirement that
non-volatile objects retain their last-stored values. Depending on
the system, it might even be able to modify the code. Or you can
just shut down the system before the program finishes.

The ability to do this kind of thing isn't generally considered to
render an implementation non-conforming.

The difference, as you say, is that argv[0]==NULL is explicitly
permitted by the C standard, so programs intended to be robust should
check it.
 
P

Phil Carmody

Ian Collins said:
I've been following this group for a number of years (probably too
many...) and in that time I don't think I've ever seen Keith insult
you or anyone else

_even when provoked_.

Phil
 
M

Malcolm McLean

Perhaps.  But, that doesn't mean that MS-DOS C compilers used that
information initially.  I certainly developed on several MS-DOS C compilers
that documented that argv[0] was "C", regardless of the executable name.
Since I never cared about it, I never noticed if/when it changed.
You tended not to use the command line with old DOS. One problem was
that there was a 256 character limit. The other, related problem was
that wildcards weren't expanded. So it tended to be a grief to write
programs that took filenames as arguments. However you knew the width
and height of your screen, so it was easy to knock up a character-
mapped GUI.
 
S

Seebs

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

I have been bitten by a close relative of this, which caused one of
several client connections to a server, quasi-randomly, to end up getting
diagnostic messages under some circumstances. (Not mine, which were
correctly moving to the selected log file, but glibc's malloc error
detection code, which uses fd 2 no matter what you've done.)
Few production-quality Unix programs defend against this, because
it's a *really* unconventional way to invoke a program. No one
(as far as I know) really expects it to be useful to do this.

I'm not sure I've ever seen it actually done on purpose. But I've seen
stuff defend against it at least in part.
(It could be a security issue for a setuid program. Fortunately
there are few of those and they are usually both simple and
carefully written.)

You are an optimist. :)

-s
 
J

James Kuyper

Perhaps. �But, that doesn't mean that MS-DOS C compilers used that
information initially. �I certainly developed on several MS-DOS C compilers
that documented that argv[0] was "C", regardless of the executable name.
Since I never cared about it, I never noticed if/when it changed.
You tended not to use the command line with old DOS.

You might not have, I did.
... One problem was
that there was a 256 character limit. The other, related problem was
that wildcards weren't expanded. ...

I find the wildcard expansion that is automatically performed by most
shells on most Unix-like systems very convenient. However, MSDOS did
offer functions that could be called to perform wildcard matching, and I
did write code making use of them.

.... So it tended to be a grief to write
programs that took filenames as arguments. However you knew the width
and height of your screen, so it was easy to knock up a character-
mapped GUI.

I almost never had a standard-sized screen. I remember that when I used
MSDOS, I set configuration parameters somewhere that gave the screen a
non-standard size (I think I had a larger number of lines, with a
smaller font size). It confused a number of programs that had built-in
assumptions like the ones you're implying, but those assumptions were
never justified, because it could be re-configured.
 
T

Tim Rentsch

Keith Thompson said:
James Kuyper said:
That's interesting (and disappointing). I had guessed that,
since execv() can easily invoke any program with argv[0]==NULL,
most production-quality Unix programs would check argv[0] before
dereferencing it. Apparently I was mistaken.

Under Unix, it's also easy to invoke a program without any file
descriptors at all, so that stdin, stdout, and stderr are all
invalid. The first fopen() successful call ends up functioning
as stdin, the next as stdout, and the next as stderr.

I wasn't aware of that option.

There's a key difference here, as far as C is concerned: argc==0 &&
argv[0]==NULL is explicitly permitted by the C standard. Having standard
streams that need to be explicitly opened is not (7.19.3p7).
[...]

Implementations typically can do all sorts of things that violate the
language standard. A debugger can modify the values of objects as
the program is running, which clearly violates the requirement that
non-volatile objects retain their last-stored values. Depending on
the system, it might even be able to modify the code. Or you can
just shut down the system before the program finishes.

The ability to do this kind of thing isn't generally considered to
render an implementation non-conforming. [snip incidental]

That's because those things aren't part of the implementation: not
debuggers, not operating systems, not physical hardware. Those things
all fall under the heading of "a data-processing system capable of
supporting a conforming implementation", which is explicitly called
out in section 1 paragraph 2 as outside what the Standard specifies.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top