Re: [PATCH v2] bisect--helper: plug strvec leak

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Oct 10, 2022 at 10:42:42PM -0700, Junio C Hamano wrote:

> >> -			struct strvec argv = STRVEC_INIT;
> >> +			const char *argv[] = { "checkout", start_head.buf,
> >> +					       "--", NULL };
> >> 
> >> -			strvec_pushl(&argv, "checkout", start_head.buf,
> >> -				     "--", NULL);
> >> -			if (run_command_v_opt(argv.v, RUN_GIT_CMD)) {
> >> +			if (run_command_v_opt(argv, RUN_GIT_CMD)) {
> >
> > This is OK with me, but note that one thing we lose is compiler
> > protection that we remembered the trailing NULL pointer in the argv
> > array (whereas strvec_pushl() has an attribute that makes sure the last
> > argument is a NULL).
> 
> The first parameter to run_command_v_opt() must be a NULL terminated
> array of strings.  argv.v[] after strvec_push*() is such a NULL
> terminated array, and is suitable to be passed to the function.
> 
> That much human programmers would know.
> 
> But does the compiler know that run_command_v_opt() requires a NULL
> terminated array of strings, and does it know to check that argv.v[]
> came from strvec_pushl() without any annotation in the first place?

No, but I don't think that's the interesting part. If you're using
strvec, it does the right thing, and it's hard to get it wrong. I'm more
concerned about places where we manually write a list of strings, and
it's easy to forget the trailing NULL.

In the existing code, that's done in the interface of strvec_pushl(),
which will remind you if you write:

  strvec_pushl(&arg, "checkout", start_head.buf, "--");

But after it is done in an initializer, which has no clue about the
expected semantics. We only have to get strvec's invariants right once.
But every ad-hoc command argv has to remember the trailing NULL.

> For such a check to happen, I think we need to tell the compiler
> with some annotation that the first parameter to run_command_v_opt()
> is supposed to be a NULL terminated char *[] array.

Right, but I would not expect the compiler to realize that strvec
maintains the ends-in-NULL invariant. It would have to be quite a clever
compiler.

In theory it could realize that argv is declared as an array locally,
and could make sure it ends in NULL as a compile-time check.

So it would have to be: "check this statically if you can, but otherwise
assume it's OK" kind of warning. But it's all kind of moot since I don't
think any such annotation exists. :)

Possibly a linter like sparse could complain about declaring a variable
called argv that doesn't end in NULL. I don't think it's worth anybody
spending too much time on it, though. This hasn't historically been a
big source of bugs.

> > Probably not that big a deal in practice. It would be nice if there was
> > a way to annotate this for the compiler, but I don't think there's any
> > attribute for "this pointer-to-pointer parameter should have a NULL at
> > the end".
> 
> But the code before this patch is safe only for strvec_pushl() call,
> not run_command_v_opt() call, so we are not losing anything, I would
> think.

The bug I'm worried about it is in a human writing the list of strings
and forgetting the NULL, so there we are losing the (admittedly minor)
protection.

-Peff



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux