Re: [bug #64551] Possible null pointer dereference on the function get_buffer

2024-01-21 Thread Paul Smith
On Sun, 2024-01-21 at 12:00 +0800, Haoxin Tu wrote:
> May I know if you are planning to propose a fix for it? I checked the
> implementations of other `make` versions a bit further, and as far as
> I can tell, the issue exists from the older make-4.0.90 (2014-9-30)
> to the newest version of make (make-4.4.0.91).

That's incorrect.  As Martin explained, and I mentioned in my replies,
this issue was resolved back in 2017 and the fix is available starting
in GNU Make 4.3 and above.

In that release, the OUT_OF_MEMORY() macro has been replaced with an
out_of_memory() function call, and neither that function nor any
function it calls will try to allocate memory and so it cannot have the
same behavior as the older code.

In the current release, out-of-memory failures write a static buffer to
a file descriptor then exit, without returning or trying to allocate
more memory.

Here is the relevant code from the current GNU Make 4.4.1 release:

https://git.savannah.gnu.org/cgit/make.git/tree/src/misc.c?h=4.4.1#n288
https://git.savannah.gnu.org/cgit/make.git/tree/src/output.c?h=4.4.1#n532
https://git.savannah.gnu.org/cgit/make.git/tree/src/misc.c?h=4.4.1#n426


As an aside, all the versions of GNU Make that end in ".9x" such as the
ones you refer to above, 4.0.90 and 4.4.0.91, are beta or release
candidate releases.  They are not fit for production use.  Any release
which is made available on the https://alpha.gnu.org/gnu/ site is a
pre-release and should only be used for testing the release.

You should only use releases with non-".9x" versions.  You can find
these releases at the official site https://ftp.gnu.org/gnu/ and they
are announced at https://savannah.gnu.org/projects/make/

-- 
Paul D. Smith Find some GNU make tips at:
https://www.gnu.org   http://make.mad-scientist.net
"Please remain calm...I may be mad, but I am a professional." --Mad
Scientist



Re: [bug #64551] Possible null pointer dereference on the function get_buffer

2024-01-21 Thread Haoxin Tu
Hi Martin and Paul,

Thanks for your detailed explanation. I have no further concerns now.

Have a great day ahead!

Best regards,
Haoxin

Paul Smith  于2024年1月21日周日 23:24写道:

> On Sun, 2024-01-21 at 12:00 +0800, Haoxin Tu wrote:
> > May I know if you are planning to propose a fix for it? I checked the
> > implementations of other `make` versions a bit further, and as far as
> > I can tell, the issue exists from the older make-4.0.90 (2014-9-30)
> > to the newest version of make (make-4.4.0.91).
>
> That's incorrect.  As Martin explained, and I mentioned in my replies,
> this issue was resolved back in 2017 and the fix is available starting
> in GNU Make 4.3 and above.
>
> In that release, the OUT_OF_MEMORY() macro has been replaced with an
> out_of_memory() function call, and neither that function nor any
> function it calls will try to allocate memory and so it cannot have the
> same behavior as the older code.
>
> In the current release, out-of-memory failures write a static buffer to
> a file descriptor then exit, without returning or trying to allocate
> more memory.
>
> Here is the relevant code from the current GNU Make 4.4.1 release:
>
> https://git.savannah.gnu.org/cgit/make.git/tree/src/misc.c?h=4.4.1#n288
> https://git.savannah.gnu.org/cgit/make.git/tree/src/output.c?h=4.4.1#n532
> https://git.savannah.gnu.org/cgit/make.git/tree/src/misc.c?h=4.4.1#n426
>
>
> As an aside, all the versions of GNU Make that end in ".9x" such as the
> ones you refer to above, 4.0.90 and 4.4.0.91, are beta or release
> candidate releases.  They are not fit for production use.  Any release
> which is made available on the https://alpha.gnu.org/gnu/ site is a
> pre-release and should only be used for testing the release.
>
> You should only use releases with non-".9x" versions.  You can find
> these releases at the official site https://ftp.gnu.org/gnu/ and they
> are announced at https://savannah.gnu.org/projects/make/
>
> --
> Paul D. Smith Find some GNU make tips at:
> https://www.gnu.org   http://make.mad-scientist.net
> "Please remain calm...I may be mad, but I am a professional." --Mad
> Scientist
>


Re: New conditional assignment facility

2024-01-21 Thread Paul Smith
On Sat, 2024-01-20 at 22:18 -0500, Dmitry Goncharov wrote:
> > Either we could follow the example of "+=" and say that the assignment
> > type in "+:=" only takes effect if the variable doesn't already have a
> > type but if it does that type is preserved, so in the above example FOO
> > would continue to be recursively expanded in spite of "+:=", so FOO has
> > a value of "$(bar) $(biz)" and $(FOO) gives "1 2".
> > 
> > Or we could say that "+=" is a special case where we follow the type of
> > the existing variable, but for the other operators we first expand the
> > right hand side then append the result regardless of the original type.
> > So in the above example FOO is still a recursive variable, BUT $(baz)
> > is expanded immediately before appending so the value of FOO would be
> > "$(bar) yy" and $(FOO) gives "1 yy".
> > 
> > Neither of these is great, in that they both will cause people to be
> > surprised, in different situations.
> 
> i like option one. It is simple to explain in the manual and, as far
> as i can tell, option one does what users want.
> As long as the manual says something like "when there is no variable
> +:= creates a simple variable, otherwise +:= behaves the same as :="
> is there still room for surprises?

I think you wrote that wrong: I think you mean "otherwise +:= behaves
the same as +="... ?

I think the behavior here would be very surprising in a number of
situations as I'll try to show below.

> i suspect option two is a lot trickier to use in a makefile. Option
> two introduces a doubt in the mind of a makefile author. If the
> makefile author knows that all the appends +=, :+=, ::+=+, :::+=

Just for clarity, it's "+=", "+:=", "+::=", "+:::=", and "+!="; the
plus is the first character in the token, not right before the "=".

> follow the variable flavor, once the variable is created, then the
> author sees that a variable is recursive at the top of a makefile and
> knows anything can be appended to the variable at the bottom of the
> makefile and the value will contain that anything at build time. If
> we go with option two then the author does not have this knowledge.
> In your example, one scenario is that the author misses that the
> assignment is +:= and sets biz to 2 and expects that FOO contains "1
> 2" at build time. Another scenario is that 'FOO +:= $(biz)' is
> introduced long after 'biz = 2'. Similarly, if the author wants to
> introduce a +:= assignment somewhere in a makefile, they have to
> check that the makefile does not contain another assignment later. In
> our example, if the author wanted to introduce FOO +:= $(biz) they
> will have to check that biz is not assigned later.

I don't think I agree with you here.

Let's take one obviously bad case: the != operator.  I don't see any
legitimate way that this can be used if we choose option one.  Suppose
we have:

$(X)foo != echo hello

foo +:= $(BAR)

Now what do we do?  We clearly can't say that the RHS of the append
assignment should be treated as a shell script!  It can't work to say
that the value to be appended _might_ be appended using simple
expansion if X has a value, _or else_ be run as a shell script and
append the result if X is empty.

And similarly for the other way around: it won't work if the value was
originally assigned with ":=" and then you use "+!=" and instead of
expanding the shell command it simply expands and appends the value.


The idea behind option two is that you don't need to know what other
settings of the variable had previously been created.  The only thing
you care about is how you want to handle THIS assignment; that is, you
expand (or not) the RHS of THIS assignment according to the operator,
then append that value.

So for example if you see "+!=" you know that the RHS of this
assignment will definitely be expanded as a shell script, then the
results will be appended to the variable.


The question is what happens in this scenario:

  foo = $(bar)

  foo +:= $(baz)

What we would like to see is that the RHS of the "+:=" is expanded
immediately (if the user didn't want it to be expanded immediately then
they'd obviously not use "+:=") then appended.  But this is kind of
gross because we're appending an already-expanded value to a recursive
variable, which means that already-expanded value will be expanded
AGAIN when the variable is expanded which is not what you want.

Similarly, what if we have:

  foo := $(bar)

  foo +:::= $(baz)

Here the foo variable is marked simple, but we are appending an escaped
value to it which won't be expanded later.

Maybe we need to consider escaping/expanding values properly for the
variable they are to be assigned to, after we expand them based on the
current operator.

I will try to write down what I'm thinking in a separate email, maybe
as a table.  The need for such a table of course is depressing because
it means we can't just have a simple rule.  But I just don't think that
a simple rule can work given all the competing

Re: New conditional assignment facility

2024-01-21 Thread Dmitry Goncharov
On Sun, Jan 21, 2024 at 11:17 AM Paul Smith  wrote:

> I think you wrote that wrong: I think you mean "otherwise +:= behaves
> the same as +="... ?

You are right.

Let us clarify the goal of these enhancements?
i assumed that the goal of these enhancements was to allow code like
hello+:=$(world)
create 'hello' as a simple variable, if 'hello' does not exist yet.

After reading your != example, i realize i misunderstood the meaning
of option one.
Let me correct myself.

If the only goal was to allow +:= create a simple variable, then can
we do the following?
"If no variable with this name exists, then +:= creates a simple
variable, and +:::= creates an immediately-expanded-and-escaped
variable. Otherwise, +:= and +:::= behave the same as +=".
If we go with this, then there is no need for +!=, because +!= would
behave as +=. Similarly, there is no need for +::=, because +::= would
behave as +:=.

regards, Dmitry



Re: Segmentation Fault on Exported Resursively Expanded Variable

2024-01-21 Thread Dmitry Goncharov
On Tue, Jan 16, 2024 at 1:21 PM Henrik Carlqvist  wrote:
>
> On Tue, 16 Jan 2024 06:59:30 +
> MIAOW Miao  wrote:
> > if ((*ep)[nl] == '=' && strncmp (*ep, v->name, nl) == 0)
>
> Looking at that line, the rather obvious fix would be to change it to:
>
> if (strncmp (*ep, v->name, nl) == 0 && (*ep)[nl] == '=')


i bet, the purpose of having (*ep)[nl] == '=' check before strncmp was
to relieve make from running strncmp unless the variables have the
same length.
Similarly, the fix attached to the savannah report
 size_t len = strlen (*ep);
 if (len >= nl && (*ep)[nl] == '=' && memcmp (*ep, v->name, nl) == 0)

does the length check before memcmp for the same purpose, to relieve
make from running memcmp, unless needed.

For every char, strncmp does two checks, n and the character. strlen
does only one check.
Without doing any measurements, i expect, strlen do better than
strncmp when strlen (*ep) is shorter than nl.
On the other hand, when v->name is half the length of *ep, we'd prefer strncmp.

regards, Dmitry



Re: Segmentation Fault on Exported Resursively Expanded Variable

2024-01-21 Thread Henrik Carlqvist
On Sun, 21 Jan 2024 14:45:00 -0500
Dmitry Goncharov  wrote:
> i bet, the purpose of having (*ep)[nl] == '=' check before strncmp was
> to relieve make from running strncmp unless the variables have the
> same length.

Yes, that is also my guess. Unfortunately, it could give a segfault if
(*ep)[nl] is not a valid memory location.

> For every char, strncmp does two checks, n and the character. strlen
> does only one check.
> Without doing any measurements, i expect, strlen do better than
> strncmp when strlen (*ep) is shorter than nl.
> On the other hand, when v->name is half the length of *ep, we'd prefer
> strncmp.

I haven't done any measurements either, but my guess is that strlen is faster
for the cases when the strlen(*ep) is shorter than about double the position
of the first different characters in *ep and v->name. So strncmp might be
faster if the strings differ in the beginning as strncmp probably will abort
at the first difference but strlen will not abort until the end of the string.
But on the other hand, strlen will be at least twice as fast for every 
position as it only cares about a single string and does not care about any
max length. 

regards Henrik