From b1c07e09771aa27108ff206e0e8881582579779d Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Mon, 15 Dec 2025 16:21:51 +0800 Subject: [PATCH 1/3] change ; to && in the eval-ed command in order to prevent the command from continuing to execute when one of the commands fails. --- plugins/sudoers/Makefile.in | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index d5578d6b6b..7e9969c34d 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -503,7 +503,7 @@ $(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y prologue else \ gram_y="$(srcdir)/gram.y"; \ fi; \ - cmd='$(YACC) -d -p sudoers '"$$gram_y"'; cp prologue $(devdir)/gram.c; $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/gram.c; sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" y.tab.h > $(devdir)/gram.h; rm -f y.tab.[ch]'; \ + cmd='$(YACC) -d -p sudoers '"$$gram_y"' && cp prologue $(devdir)/gram.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/gram.c && sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" y.tab.h > $(devdir)/gram.h && rm -f y.tab.[ch]'; \ echo "$$cmd"; eval $$cmd; \ fi @@ -514,7 +514,7 @@ $(devdir)/toke.c: $(srcdir)/toke.l prologue else \ toke_l="$(srcdir)/toke.l"; \ fi; \ - cmd='$(FLEX) '"$$toke_l"'; cp prologue $(devdir)/toke.c; $(SED) -e "s/^\\(#line .*\\) \"lex\\.sudoers\\.c\"/\1 \"toke.c\"/" -e "s:/\* *FALLTHROUGH *\*/:FALLTHROUGH;:" lex.sudoers.c >> $(devdir)/toke.c; rm -f lex.sudoers.c'; \ + cmd='$(FLEX) '"$$toke_l"' && cp prologue $(devdir)/toke.c && $(SED) -e "s/^\\(#line .*\\) \"lex\\.sudoers\\.c\"/\1 \"toke.c\"/" -e "s:/\* *FALLTHROUGH *\*/:FALLTHROUGH;:" lex.sudoers.c >> $(devdir)/toke.c && rm -f lex.sudoers.c'; \ echo "$$cmd"; eval $$cmd; \ fi @@ -526,7 +526,7 @@ $(devdir)/getdate.c: $(srcdir)/getdate.y prologue else \ getdate_y="$(srcdir)/getdate.y"; \ fi; \ - cmd='$(YACC) '"$$getdate_y"'; cp prologue $(devdir)/getdate.c; $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"getdate.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/getdate.c; rm -f y.tab.c'; \ + cmd='$(YACC) '"$$getdate_y"' && cp prologue $(devdir)/getdate.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"getdate.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/getdate.c && rm -f y.tab.c'; \ echo "$$cmd"; eval $$cmd; \ fi From 2e83ae0691570fac63e9df7d9f18a93411c590c7 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Mon, 15 Dec 2025 16:25:33 +0800 Subject: [PATCH 2/3] Use a stamp file to mark the multiple outputs of one command When one command generates multiple outputs, using a naive one-to-two depency would introduce race condition when doing parallel compilation. For example, when the rules are written in this pattern: foo.c foo.h: foo.y command foo.y generating foo.c and foo.h some-target: foo.c some command reading foo.c some-other-target: foo.h some command reading foo.h and the targets are built in parallel, `command foo.y` may be executed twice because make thinks `command foo.y` can be used to generate foo.c and can also be used to generate foo.h. What's worse, one of the commands reading foo.c or foo.h may read an incomplete input during the command generating the other one is running. This pattern happens on the rules of def_data.in and gram.y. This commit fixes this by using a stamp file to witness the execution of the `command foo.y`, following the advice in the automake manual [1]. [1]: https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html --- plugins/sudoers/Makefile.in | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 7e9969c34d..4de80d3484 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -491,12 +491,16 @@ run-fuzz_sudoers_ldif: fuzz_sudoers_ldif done; \ ./fuzz_sudoers_ldif -dict=$(srcdir)/regress/fuzz/fuzz_sudoers_ldif.dict -max_len=$(FUZZ_MAX_LEN) -runs=$(FUZZ_RUNS) $(FUZZ_VERBOSE) $$corpus -GENERATED = gram.h gram.c toke.c def_data.c def_data.h getdate.c +GENERATED = gram.h gram.c gram.stamp toke.c def_data.c def_data.h def_data.stamp getdate.c prologue: echo "#include " >> $@ -$(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y prologue +$(devdir)/gram.c $(devdir)/gram.h: $(devdir)/gram.stamp + @if [ ! -f $@ ]; then rm -f $<; false; fi +$(devdir)/gram.stamp: $(srcdir)/gram.y prologue + @rm -f $(devdir)/gram.tmp + @touch $(devdir)/gram.tmp @if [ -n "$(DEVEL)" ]; then \ if test "$(srcdir)" = "."; then \ gram_y="gram.y"; \ @@ -506,6 +510,7 @@ $(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y prologue cmd='$(YACC) -d -p sudoers '"$$gram_y"' && cp prologue $(devdir)/gram.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/gram.c && sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" y.tab.h > $(devdir)/gram.h && rm -f y.tab.[ch]'; \ echo "$$cmd"; eval $$cmd; \ fi + @mv -f $(devdir)/gram.tmp $@ $(devdir)/toke.c: $(srcdir)/toke.l prologue @if [ -n "$(DEVEL)" ]; then \ @@ -530,11 +535,16 @@ $(devdir)/getdate.c: $(srcdir)/getdate.y prologue echo "$$cmd"; eval $$cmd; \ fi -$(devdir)/def_data.c $(devdir)/def_data.h: $(srcdir)/def_data.in +$(devdir)/def_data.c $(devdir)/def_data.h: $(devdir)/def_data.stamp + @if [ ! -f $@ ]; then rm -f $<; false; fi +$(devdir)/def_data.stamp: $(srcdir)/def_data.in + @rm -f $(devdir)/def_data.tmp + @touch $(devdir)/def_data.tmp @if [ -n "$(DEVEL)" ]; then \ cmd='AWK=$(AWK) $(SHELL) $(srcdir)/mkdefaults -o $(devdir)/def_data $(srcdir)/def_data.in'; \ echo "$$cmd"; eval $$cmd; \ fi + @mv -f $(devdir)/def_data.tmp $@ tsgetusershell.c: $(top_srcdir)/lib/util/getusershell.c printf '#define TESTSUDOERS\n\n' > $@ From cc1a0bcce60c6f151a45bd131ba6b5f6e887bce7 Mon Sep 17 00:00:00 2001 From: Miao Wang Date: Mon, 15 Dec 2025 16:44:41 +0800 Subject: [PATCH 3/3] Run yacc in separate directories The targets for generating getdate.c and gram.c/h run yacc in the same directory and post-process the generated y.tab.c/h by yacc into the final target. They both generate temporary y.tab.c/h files with the same name and they may overwrite each other if built in parallel. This commit fixes this by let yacc run in individual temporary directories to prevent them from overwriting each other. --- plugins/sudoers/Makefile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in index 4de80d3484..8ebc4660a0 100644 --- a/plugins/sudoers/Makefile.in +++ b/plugins/sudoers/Makefile.in @@ -507,7 +507,7 @@ $(devdir)/gram.stamp: $(srcdir)/gram.y prologue else \ gram_y="$(srcdir)/gram.y"; \ fi; \ - cmd='$(YACC) -d -p sudoers '"$$gram_y"' && cp prologue $(devdir)/gram.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/gram.c && sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" y.tab.h > $(devdir)/gram.h && rm -f y.tab.[ch]'; \ + cmd='mkdir -p gram && cd gram && $(YACC) -d -p sudoers '"$$(realpath "$$gram_y")"' && cd .. && cp prologue $(devdir)/gram.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"gram.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" gram/y.tab.c >> $(devdir)/gram.c && sed -e "s/^\\(#line .*\\) \"y\\.tab\\.h\"/\1 \"gram.h\"/" gram/y.tab.h > $(devdir)/gram.h && rm -rf gram/'; \ echo "$$cmd"; eval $$cmd; \ fi @mv -f $(devdir)/gram.tmp $@ @@ -531,7 +531,7 @@ $(devdir)/getdate.c: $(srcdir)/getdate.y prologue else \ getdate_y="$(srcdir)/getdate.y"; \ fi; \ - cmd='$(YACC) '"$$getdate_y"' && cp prologue $(devdir)/getdate.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"getdate.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" y.tab.c >> $(devdir)/getdate.c && rm -f y.tab.c'; \ + cmd='mkdir -p getdate && cd getdate && $(YACC) '"$$(realpath "$$getdate_y")"' && cd .. && cp prologue $(devdir)/getdate.c && $(SED) -e "s/^\\(#line .*\\) \"y\\.tab\\.c\"/\1 \"getdate.c\"/" -e "/^# *include /{N;s/__STDC_VERSION__ && 199901 <= __STDC_VERSION__/HAVE_STDINT_H/;}" getdate/y.tab.c >> $(devdir)/getdate.c && rm -rf getdate/'; \ echo "$$cmd"; eval $$cmd; \ fi