Hi Eric,

Eric Blake <ebl...@redhat.com> writes:

> On 3/7/19 11:33 AM, Nikolai Merinov wrote:
>> In the following call sequence
>>> ./configure CPPFLAGS='-DVARIABLE=\"string\"' && make
>> compilation with the `AC_COMPILE_IFELSE' macro and with the `make'
>> command should use same compilation commands. It means that the
>> `AC_COMPILE_IFELSE' macro should evaluate the `ac_compile` variable
>> twice in order to evaluate user-supplied variables.
>
> eval'ing user-supplied text can be dangerous, as the user can supply
> arbitrary shell code if their text is not carefully sanitized.
>
> I'm not quite sure what you are trying to accomplish: Given a command
> line (or environment variable, since CPPFLAGS is precious), are you
> trying to have user input of:
>
> CPPFLAGS='-DVARIABLE=\"string\"'
>
> result in the Makefile using:
>
> CPPFLAGS = -DVARIABLE="string"
No, resulting makefile will be the following:

CPPFLAGS = -DVARIABLE=\"string\"

because signle-quotes preserve the literal value of each character
within the single-quotes. You can check the following code:

    configure.ac
        AC_INIT([Example application], [0.1])
        AM_INIT_AUTOMAKE

        AC_PROG_CC
        # CPPFLAGS='-DVARIABLE="string"' required
        AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], 
[printf("%s\n", VARIABLE)])], [],
          [AC_MSG_ERROR([compiling trivial program failed])])

        AC_CONFIG_FILES(Makefile)
        AC_OUTPUT

    Makefile.am
        bin_PROGRAMS = prog
        prog_SOURCES = main.c

    main.c
        #include <stdio.h>
        int main() {
          /* CPPFLAGS='-DVARIABLE=\"string\"' required */
          printf("%s\n", VARIABLE);
          return 0;
        }

We have a same code in the AC_COMPILE_IFELSE call and in the main.c
file, but it is impossible to configure and compile a code with the same
CPPFLAGS value.

>
> (which would compile as if written:
> #define VARIABLE string
> because make expands $(CPPFLAGS) before invoking sh that eats the ") or in:
>
> CPPFLAGS = -DVARIABLE=\"string\"
>
> (which would compile as if written:
> #define VARIABLE "string"
> because sh eats the \ but leaves the ")
>
> At which point, are you arguing that if make is going to pass through
> another shell and eat a layer of quotation, then configure should do
> likewise for any use of those same variables?
>
>> +++ b/tests/compile.at
>> @@ -301,6 +301,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [return 2])],
>>  AT_CHECK_AUTOCONF
>>  AT_CHECK_CONFIGURE([-q])
>>  
>> +AT_DATA([configure.ac],
>> +[[AC_INIT
>> +AC_PROG_CC
>> +test x$GCC = xyes && CFLAGS='"-Wall"'
>
> Okay, this helps - it looks like you are indeed arguing that the
> Makefile will end up with:
>
> CFLAGS = "-Wall"
>
> but those quotes get eaten by shell; so our use of ${CFLAGS} during
> configure should use the same level of quotation stripping as what the
> resulting makefile will.
>
> Your patch could use a NEWS entry for the change.

Added. New patch attached.

Regards,
Nikolai

>From ce3a819f067c9da804081f8e659596ad384ff3d3 Mon Sep 17 00:00:00 2001
From: Nikolai Merinov <nikolai.meri...@member.fsf.org>
Date: Thu, 7 Mar 2019 22:33:13 +0500
Subject: [PATCH] AC_COMPILE_IFELSE: Evaluate user supplied arguments

In the following call sequence
> ./configure CPPFLAGS='-DVARIABLE=\"string\"' && make
compilation with the `AC_COMPILE_IFELSE' macro and with the `make'
command should use same compilation commands. It means that the
`AC_COMPILE_IFELSE' macro should evaluate the `ac_compile` variable
twice in order to evaluate user-supplied variables.

* lib/autoconf/general.m4 (_AC_DO_STDERR): Reuse `_AC_DO_ECHO' trick
to evaluate arguments twice if compile string have no '\"', '`', or
'\\' symbols.
* tests/compile.at: Add test for CFLAGS evaluation.
---
 NEWS                    |  5 +++++
 lib/autoconf/general.m4 | 11 +++++++++--
 tests/compile.at        | 11 +++++++++++
 3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index efade585..4ac8d683 100644
--- a/NEWS
+++ b/NEWS
@@ -123,6 +123,11 @@ GNU Autoconf NEWS - User visible changes.
   use with multiple languages, rather than forcing all checks in the
   language used by the first encounter of the macro.
 
+- The _AC_DO_STDERR macro now evaluate a COMMAND argument twice. This
+  change consolidate behavior for user-supplied arguments between the
+  AC_COMPILE_IFELSE and AC_LINK_IFELSE macros and compilation commands
+  used in makefiles.
+
 ** Man pages for config.guess and config.sub are no longer provided.
 They were moved to the master source tree for config.guess and config.sub.
 
diff --git a/lib/autoconf/general.m4 b/lib/autoconf/general.m4
index e1d82b54..0e816f4b 100644
--- a/lib/autoconf/general.m4
+++ b/lib/autoconf/general.m4
@@ -2456,8 +2456,15 @@ AC_DEFUN([_AC_DO],
 # ----------------------
 # Like _AC_RUN_LOG_STDERR, but eval (instead of running) COMMAND.
 AC_DEFUN([_AC_DO_STDERR],
-[_AC_RUN_LOG_STDERR([eval "$1"],
-		    [_AC_DO_ECHO([$1])])])
+[m4_if([$1], [$ac_do_stderr], [], [ac_do_stderr="$1"
+])]dnl
+[[case "(($ac_do_stderr" in
+  *\"* | *\`* | *\\*) ac_do_stderr_command=\$ac_do_stderr;;
+  *) ac_do_stderr_command=$ac_do_stderr;;
+esac
+eval ac_do_stderr_command="\"$ac_do_stderr_command\""]
+_AC_RUN_LOG_STDERR([eval "$ac_do_stderr_command"],
+		   [_AC_DO_ECHO([$ac_do_stderr])])])
 
 
 # _AC_DO_VAR(VARIABLE)
diff --git a/tests/compile.at b/tests/compile.at
index 29374529..9af8cb38 100644
--- a/tests/compile.at
+++ b/tests/compile.at
@@ -301,6 +301,17 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [return 2])],
 AT_CHECK_AUTOCONF
 AT_CHECK_CONFIGURE([-q])
 
+AT_DATA([configure.ac],
+[[AC_INIT
+AC_PROG_CC
+test x$GCC = xyes && CFLAGS='"-Wall"'
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [return 0])], [],
+  [AC_MSG_ERROR([compiling trivial program failed])])
+]])
+
+AT_CHECK_AUTOCONF
+AT_CHECK_CONFIGURE([-q])
+
 AT_CLEANUP
 
 ## --------------- ##
-- 
2.20.0

Reply via email to