|
|
Subscribe / Log in / New account

Handling argc==0 in the kernel

Handling argc==0 in the kernel

Posted Jan 31, 2022 19:10 UTC (Mon) by marcH (subscriber, #57642)
In reply to: Handling argc==0 in the kernel by jem
Parent article: Handling argc==0 in the kernel

> One might also argue that argc is superfluous, ...

Yes and that would be very ironic in an article about a pkexec security issue caused by not using argc as termination and fixed by looking at it :-)

Anyway comparing termination in C versus all other programming languages was not my point. Using _both_ argc and NULL at the same time is idiomatic in exactly zero programming language, so that's confusing. So I'm merely suggesting adding one short sentence about that.


to post comments

Handling argc==0 in the kernel

Posted Jan 31, 2022 19:42 UTC (Mon) by nybble41 (subscriber, #55106) [Link] (4 responses)

> caused by not using argc as termination

One could equally well cast this issue as "caused by not checking the first element of the array for the NULL terminator". It's exactly the same error as if you received a NUL-terminated string and started iterating over it from the second element, assuming the string to be non-empty.

I'm in the Pascal-style string/list camp myself—lengths should be explicit—but using argc instead of checking for NULL is neither necessary nor sufficient to avoid this problem. (To illustrate the latter, consider the case of a program making the same non-empty argv assumption and using a loop of the form "int i = 1; do { ... } while (i++ < argc)" to shave off a "redundant" bounds check.)

Handling argc==0 in the kernel

Posted Jan 31, 2022 19:57 UTC (Mon) by marcH (subscriber, #57642) [Link] (3 responses)

> One could equally well cast this issue as "caused by not checking the first element of the array for the NULL terminator". It's exactly the same error as if you received a NUL-terminated string and started iterating over it from the second element, assuming the string to be non-empty.

It's "exactly the same" only if your termination looks like "i != argc" but no one ever does that. Everyone does "i < argc" or something like it. I mean no one writes:

for (int i; i++; i!=argc)

> but using argc instead of checking for NULL is neither necessary nor sufficient to avoid this problem.

I haven't looked at the actual code but if pkexec's loop had used an argc-based termination then the loop would have not run at all.

> int i = 1; do { ... } while (i++ < argc)" to shave off a "redundant" bounds check.)

That's bending over backwards to avoid a simpler for loop. I'm sure you can find some real world and valid cases for this but most of the time people just write a simpler for loop.

Handling argc==0 in the kernel

Posted Jan 31, 2022 22:19 UTC (Mon) by marcH (subscriber, #57642) [Link]

> for (int i; i++; i!=argc)

Of course I meant no one writes this:

for (int i=start; i!=argc; i++)

Sorry for the noise.

Handling argc==0 in the kernel

Posted Feb 1, 2022 1:58 UTC (Tue) by NYKevin (subscriber, #129325) [Link] (1 responses)

> It's "exactly the same" only if your termination looks like "i != argc" but no one ever does that. Everyone does "i < argc" or something like it. I mean no one writes:
>
> for (int i; i++; i!=argc)

Maybe not in C, but C++ tacitly encourages this sort of nonsense because iterators are not, strictly speaking, required to be ordered (for example, a linked-list iterator may only be comparable for equality, because there is no O(1) way of ordering two iterators). So if you're taking C++ code and porting it to straight C, the most straightforward translation of a foreach loop is to use an inequality comparison instead of a less-than comparison, and it's possible that some programmers who started out as C++ programmers and later learned C may have picked this up as an idiom.

(Incidentally, these people also tend to favor the preincrement operator over the postincrement operator in contexts where there's no semantic difference, because in C++, postincrement can be significantly costlier due to the need to make a copy.)

Handling argc==0 in the kernel

Posted Feb 1, 2022 12:59 UTC (Tue) by madscientist (subscriber, #16861) [Link]

In my experience with C++, people use < most of the time when looping over integers. You can't perform integer looping with an iterator, unless you add your own specializations which people don't really bother to do, so these kinds of loops are written differently than loops with STL iterators anyway.

Also even in C, old-school programmers preferred pre-increment because post-increment was less efficient. Of course it was hard to detect that inefficiency, but it was a peg to hang one's preferential hat on and that's all that's needed when faced with two essentially equivalent choices. In C++ with operator overloading it can be measurably less efficient, of course, depending on the type implementation.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds