diff --git a/dist b/dist new file mode 100644 index 0000000000000000000000000000000000000000..9c0e36ec42a2d9bfefacb21ac6354c9ddd910533 --- /dev/null +++ b/dist @@ -0,0 +1 @@ +an8 diff --git a/gcc.spec b/gcc.spec index b4e229fbf1a6cf6349b60effdeec76b9b1030708..9a8f857807d3814b37e92656239ec1d86f355944 100644 --- a/gcc.spec +++ b/gcc.spec @@ -1,11 +1,11 @@ -%define anolis_release .0.3 +%define anolis_release .0.1 %global DATE 20210514 %global gitrev a3253c88425835d5b339d6998a1110a66ccd8b44 %global gcc_version 8.5.0 %global gcc_major 8 # Note, gcc_release must be integer, if you want to add suffixes to # %%{release}, append them after %%{gcc_release} on Release: line. -%global gcc_release 10 +%global gcc_release 18 %global nvptx_tools_gitrev c28050f60193b3b95a18866a96f03334e874e78f %global nvptx_newlib_gitrev aadc8eb0ec43b7cd0dd2dfb484bae63c8b05ef24 %global _unpackaged_files_terminate_build 0 @@ -106,11 +106,12 @@ Summary: Various compilers (C, C++, Objective-C, ...) Name: gcc Version: %{gcc_version} -Release: %{gcc_release}.1%{anolis_release}%{?dist} +Release: %{gcc_release}%{anolis_release}%{?dist} # libgcc, libgfortran, libgomp, libstdc++ and crtstuff have # GCC Runtime Exception. License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions and LGPLv2+ and BSD Group: Development/Languages +Excludearch: loongarch64 # The source for this package was pulled from upstream's vcs. Use the # following commands to generate the tarball: # git clone --depth 1 git://gcc.gnu.org/git/gcc.git gcc-dir.tmp @@ -201,7 +202,7 @@ Requires: libisl.so.15 %endif %if %{build_libstdcxx_docs} BuildRequires: doxygen >= 1.7.1 -BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook5-style-xsl +BuildRequires: graphviz, dblatex, texlive-collection-latex, docbook-style-xsl %endif Requires: cpp = %{version}-%{release} # Need .eh_frame ld optimizations @@ -287,10 +288,19 @@ Patch24: gcc8-pch-tweaks.patch Patch25: gcc8-aarch64-mtune-neoverse-512tvb.patch Patch26: gcc8-rh2028609.patch Patch27: gcc8-libgfortran-default-values.patch - +Patch28: gcc8-rh2001788.patch +Patch29: gcc8-rh2117838.patch Patch30: gcc8-rh1668903-1.patch Patch31: gcc8-rh1668903-2.patch Patch32: gcc8-rh1668903-3.patch +Patch33: gcc8-harden-1.patch +Patch34: gcc8-harden-2.patch +Patch35: gcc8-harden-3.patch +Patch36: gcc8-harden-4.patch +Patch37: gcc8-pr105502.patch +Patch38: gcc8-pr99536.patch +Patch39: gcc8-libstdc++-make_shared.patch +Patch40: gcc8-rh2137448.patch Patch1000: nvptx-tools-no-ptxas.patch Patch1001: nvptx-tools-build.patch @@ -845,6 +855,25 @@ NVidia PTX. OpenMP and OpenACC programs linked with -fopenmp will by default add PTX code into the binaries, which can be offloaded to NVidia PTX capable devices if available. +%package plugin-annobin +Summary: The annobin plugin for gcc, built by the installed version of gcc +Requires: gcc = %{version}-%{release} +# Starting with release 10.01 annobin fixed a bug in its configure scripts +# which prevented them from working with a built but not installed compiler +BuildRequires: annobin >= 10.01 +# Starting with release 9.93 annobin-plugin-gcc puts a copy of the sources +# in /usr/src/annobin +# FIXME: Currently the annobin-plugin-gcc subpackage only exists in Fedora. +# For RHEL-9 the annobin package does everything. +# BuildRequires: annobin-plugin-gcc +# Needed in order to be able to decompress the annobin source tarball. +BuildRequires: xz + +%description plugin-annobin +This package adds a version of the annobin plugin for gcc. This version +of the plugin is explicitly built by the same version of gcc that is installed +so that there cannot be any synchronization problems. + %prep %setup -q -n gcc-%{version}-%{DATE} -a 1 -a 2 %patch0 -p0 -b .hack~ @@ -882,10 +911,20 @@ to NVidia PTX capable devices if available. %patch25 -p1 -b .neoverse~ %patch26 -p1 -b .rh2028609~ %patch27 -p1 -b .libgfortran-default~ +%patch28 -p1 -b .rh2001788~ +%patch29 -p1 -b .rh2117838~ %patch30 -p0 -b .rh1668903-1~ %patch31 -p0 -b .rh1668903-2~ %patch32 -p0 -b .rh1668903-3~ +%patch33 -p1 -b .harden-1~ +%patch34 -p1 -b .harden-2~ +%patch35 -p1 -b .harden-3~ +%patch36 -p1 -b .harden-4~ +%patch37 -p1 -b .pr105502~ +%patch38 -p1 -b .pr99536~ +%patch39 -p1 -b .make_shared~ +%patch40 -p1 -b .rh2137448~ cd nvptx-tools-%{nvptx_tools_gitrev} %patch1000 -p1 -b .nvptx-tools-no-ptxas~ @@ -1245,6 +1284,82 @@ done) rm -f rpm.doc/changelogs/gcc/ChangeLog.[1-9] find rpm.doc -name \*ChangeLog\* | xargs bzip2 -9 +# Get the annobin sources. Note these are not added to the rpm as SOURCE4 +# because if they were the build phase would try to include them as part of +# gcc itself, and this causes problems. Instead we locate the sources in +# the buildroot. They should have been put there when annobin was installed. + +pushd %{_builddir} + +%global annobin_source_dir %{_usrsrc}/annobin + +if [ -d %{annobin_source_dir} ] +then + # Unpack the sources. + echo "Unpacking annobin sources" + rm -fr annobin-* + tar xvf %{annobin_source_dir}/latest-annobin.tar.xz + + # Setting this as a local symbol because using %%global does not appear to work. + annobin_dir=$(find . -maxdepth 1 -type d -name "annobin*") + + # Now build the annobin plugin using the just built compiler. + echo "annobin directory = ${annobin_dir}" + cd ${annobin_dir} + + # Change the plugin so that it generates "nop" instead of ".nop" instructions. + sed -e "s/\.nop/nop/" -i gcc-plugin/annobin.cc + + # Work out where this version of gcc stores its plugins. +%global ANNOBIN_GCC_PLUGIN_DIR %{_prefix}/lib/gcc/%{gcc_target_platform}/%{gcc_major}/plugin + + CONFIG_ARGS="--quiet" + CONFIG_ARGS="$CONFIG_ARGS --with-gcc-plugin-dir=%{ANNOBIN_GCC_PLUGIN_DIR}" + CONFIG_ARGS="$CONFIG_ARGS --without-annocheck" + CONFIG_ARGS="$CONFIG_ARGS --without-tests" + CONFIG_ARGS="$CONFIG_ARGS --disable-rpath" + + comp_dir="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/" + ccompiler="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/xgcc -B $comp_dir" + cxxcompiler="%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/xg++ -B $comp_dir" + + comp_flags="%build_cflags" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/gcc" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/gcc/" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/include" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/include/%{gcc_target_platform}" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/libstdc++-v3/libsupc++" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/include" + comp_flags="$comp_flags -I %{_builddir}/gcc-%{version}-%{DATE}/libcpp/include" + + ld_flags="%build_ldflags" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/libstdc++-v3/.libs" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/.libs" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/src/.libs" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/libstdc++-v3/libsupc++/.libs" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libstdc++-v3/libsupc++/.libs" + ld_flags="$ld_flags -L%{_builddir}/gcc-%{version}-%{DATE}/obj-%{gcc_target_platform}/%{gcc_target_platform}/libgcc/.libs" + + # libtool works with CFLAGS but ignores LDFLAGS, so we have to combine them. + comp_flags="$comp_flags $ld_flags" + + echo "Configuring the annobin plugin" + CC="${ccompiler}" CFLAGS="${comp_flags}" \ + CXX="${cxxcompiler}" CXXFLAGS="${comp_flags}" \ + LDFLAGS="${ld_flags}" \ + ./configure ${CONFIG_ARGS} || cat config.log + + echo "Building the annobin plugin" + make + + echo "Annobin plugin build complete" +else + echo "Unable to locate annobin sources (expected to find: %{annobin_source_dir}/latest-annobin.tar.xz)" + echo "These should be provided by installing the annobin package" + exit 1 +fi +popd + %install rm -rf %{buildroot} @@ -2024,6 +2139,19 @@ rm -f %{buildroot}%{mandir}/man3/ffi* # Help plugins find out nvra. echo gcc-%{version}-%{release}.%{_arch} > $FULLPATH/rpmver +# Rename the annobin plugin to gcc-annobin. +mkdir -p %{buildroot}%{ANNOBIN_GCC_PLUGIN_DIR} +pushd %{buildroot}%{ANNOBIN_GCC_PLUGIN_DIR} + +annobin_dir=$(find %{_builddir} -maxdepth 1 -type d -name "annobin*") +echo "annobin directory = ${annobin_dir}" + +cp ${annobin_dir}/gcc-plugin/.libs/annobin.so.0.0.0 gcc-annobin.so.0.0.0 + +rm -f gcc-annobin.so.0 gcc-annobin.so +ln -s gcc-annobin.so.0.0.0 gcc-annobin.so.0 +ln -s gcc-annobin.so.0.0.0 gcc-annobin.so +popd %ifarch loongarch64 cp %{_builddir}/gcc-%{version}-%{DATE}/gcc/config/vxworks.h %{buildroot}%{_prefix}/lib/gcc/%{_target_platform}/8/plugin/include/config %endif @@ -3239,20 +3367,47 @@ fi %{_prefix}/%{_lib}/libgomp-plugin-nvptx.so.* %endif +%files plugin-annobin +%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so +%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so.0 +%{ANNOBIN_GCC_PLUGIN_DIR}/gcc-annobin.so.0.0.0 + %changelog -* Fri Dec 2 2022 Xing Li 8.5.0-10.1.0.3 +* Tue Jun 06 2023 Xue haolin 8.5.0-18.0.1 +- Rebrand for Anolis OS. (xuehaolin@openanolis.org) +- Add loongarch support. (lixing@loongson.cn) +- Fixup LoongArch configure file error. (lixing@loongson.cn) - rename mt file for LoongArch. (lixing@loongson.cn) - Fixup LoongArch atomic_exchange error. (lixing@loongson.cn) +- Remove loongarch64 arch (wb-zh951434@alibaba-inc.com) -* Mon Oct 31 2022 Xing Li 8.5.0-10.1.0.2 -- Fixup LoongArch configure file error. (lixing@loongson.cn) +* Tue Dec 6 2022 Marek Polacek 8.5.0-18 +- fix strlen range with a flexible member array (#2137448) -* Tue Jul 5 2022 Xue haolin 8.5.0-10.1.0.1 -- Rebrand for Anolis OS. (xuehaolin@openanolis.org) -- Add loongarch support. (lixing@loongson.cn) +* Mon Oct 3 2022 Marek Polacek 8.5.0-17 +- fix deserialization for std::normal_distribution (#2130392, + PR libstdc++/105502) +- initialize std::normal_distribution::_M_saved (PR libstdc++/99536) +- reject std::make_shared (PR libstdc++/99006) + +* Thu Sep 29 2022 Marek Polacek 8.5.0-16 +- avoid changing PHIs in GIMPLE split_edge (#2117838) + +* Wed Jul 20 2022 Marek Polacek 8.5.0-15 +- backport straight-line-speculation mitigation (#2108721) + +* Fri Jul 8 2022 Jonathan Wakely 8.5.0-14 +- backport std::regex check for invalid range (#2001788) + +* Wed Apr 20 2022 Marek Polacek 8.5.0-13 +- require docbook-style-xsl instead of docbook5-style-xsl (#2073888) +- backport Default widths with -fdec-format-defaults patch (#2074614) + +* Fri Apr 01 2022 Marek Polacek 8.5.0-12 +- Fix nop generation in annobin plugin. (#2067150) -* Wed Apr 27 2022 Marek Polacek 8.5.0-10.1 -- backport Default widths with -fdec-format-defaults patch (#2079578) +* Wed Mar 30 2022 Marek Polacek 8.5.0-11 +- Add a plugin-annobin subpackage. (#2067150) * Thu Jan 27 2022 Marek Polacek 8.5.0-10 - fix typo in the cprop_hardreg patch (#2028609) diff --git a/gcc8-harden-1.patch b/gcc8-harden-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..a325c094bbe63175ae6e98fbc7a5d3cbcb5abfd1 --- /dev/null +++ b/gcc8-harden-1.patch @@ -0,0 +1,294 @@ +From 88bf1c3910e4cf97dcb85c6d32291c23e572a516 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 27 Oct 2021 07:48:54 -0700 +Subject: [PATCH 1/4] x86: Add -mharden-sls=[none|all|return|indirect-branch] + +Add -mharden-sls= to mitigate against straight line speculation (SLS) +for function return and indirect branch by adding an INT3 instruction +after function return and indirect branch. + +gcc/ + + PR target/102952 + * config/i386/i386-opts.h (harden_sls): New enum. + * config/i386/i386.c (output_indirect_thunk): Mitigate against + SLS for function return. + (ix86_output_function_return): Likewise. + (ix86_output_jmp_thunk_or_indirect): Mitigate against indirect + branch. + (ix86_output_indirect_jmp): Likewise. + (ix86_output_call_insn): Likewise. + * config/i386/i386.opt: Add -mharden-sls=. + * doc/invoke.texi: Document -mharden-sls=. + +gcc/testsuite/ + + PR target/102952 + * gcc.target/i386/harden-sls-1.c: New test. + * gcc.target/i386/harden-sls-2.c: Likewise. + * gcc.target/i386/harden-sls-3.c: Likewise. + * gcc.target/i386/harden-sls-4.c: Likewise. + * gcc.target/i386/harden-sls-5.c: Likewise. + +(cherry picked from commit 53a643f8568067d7700a9f2facc8ba39974973d3) +--- + gcc/config/i386/i386-opts.h | 7 +++++++ + gcc/config/i386/i386.c | 22 +++++++++++++++----- + gcc/config/i386/i386.opt | 20 ++++++++++++++++++ + gcc/doc/invoke.texi | 10 ++++++++- + gcc/testsuite/gcc.target/i386/harden-sls-1.c | 14 +++++++++++++ + gcc/testsuite/gcc.target/i386/harden-sls-2.c | 14 +++++++++++++ + gcc/testsuite/gcc.target/i386/harden-sls-3.c | 14 +++++++++++++ + gcc/testsuite/gcc.target/i386/harden-sls-4.c | 16 ++++++++++++++ + gcc/testsuite/gcc.target/i386/harden-sls-5.c | 17 +++++++++++++++ + 9 files changed, 128 insertions(+), 6 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-1.c + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-2.c + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-3.c + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-4.c + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-5.c + +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h +index 46366cbfa72..34718b6d52c 100644 +--- a/gcc/config/i386/i386-opts.h ++++ b/gcc/config/i386/i386-opts.h +@@ -119,4 +119,11 @@ enum indirect_branch { + indirect_branch_thunk_extern + }; + ++enum harden_sls { ++ harden_sls_none = 0, ++ harden_sls_return = 1 << 0, ++ harden_sls_indirect_branch = 1 << 1, ++ harden_sls_all = harden_sls_return | harden_sls_indirect_branch ++}; ++ + #endif +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 31502774ef3..eb9303f8742 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -10977,6 +10977,9 @@ output_indirect_thunk (enum indirect_thunk_prefix need_prefix, + fputs ("\tbnd ret\n", asm_out_file); + else + fputs ("\tret\n", asm_out_file); ++ ++ if ((ix86_harden_sls & harden_sls_return)) ++ fputs ("\tint3\n", asm_out_file); + } + + /* Output a funtion with a call and return thunk for indirect branch. +@@ -28728,6 +28731,8 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, + fprintf (asm_out_file, "\tjmp\t"); + assemble_name (asm_out_file, thunk_name); + putc ('\n', asm_out_file); ++ if ((ix86_harden_sls & harden_sls_indirect_branch)) ++ fputs ("\tint3\n", asm_out_file); + } + else + output_indirect_thunk (need_prefix, regno); +@@ -28973,10 +28978,10 @@ ix86_output_indirect_jmp (rtx call_op) + gcc_unreachable (); + + ix86_output_indirect_branch (call_op, "%0", true); +- return ""; + } + else +- return "%!jmp\t%A0"; ++ output_asm_insn ("%!jmp\t%A0", &call_op); ++ return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : ""; + } + + /* Output function return. CALL_OP is the jump target. Add a REP +@@ -29018,9 +29023,11 @@ ix86_output_function_return (bool long_p) + } + + if (!long_p || ix86_bnd_prefixed_insn_p (current_output_insn)) +- return "%!ret"; ++ output_asm_insn ("%!ret", NULL); ++ else ++ output_asm_insn ("rep%; ret", NULL); + +- return "rep%; ret"; ++ return (ix86_harden_sls & harden_sls_return) ? "int3" : ""; + } + + /* Output indirect function return. RET_OP is the function return +@@ -29158,7 +29165,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) + if (output_indirect_p && !direct_p) + ix86_output_indirect_branch (call_op, xasm, true); + else +- output_asm_insn (xasm, &call_op); ++ { ++ output_asm_insn (xasm, &call_op); ++ if (!direct_p ++ && (ix86_harden_sls & harden_sls_indirect_branch)) ++ return "int3"; ++ } + return ""; + } + +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt +index d9bd909a885..3ae48609e25 100644 +--- a/gcc/config/i386/i386.opt ++++ b/gcc/config/i386/i386.opt +@@ -1055,3 +1055,23 @@ Support MOVDIRI built-in functions and code generation. + mmovdir64b + Target Report Mask(ISA_MOVDIR64B) Var(ix86_isa_flags2) Save + Support MOVDIR64B built-in functions and code generation. ++ ++mharden-sls= ++Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none) ++Generate code to mitigate against straight line speculation. ++ ++Enum ++Name(harden_sls) Type(enum harden_sls) ++Known choices for mitigation against straight line speculation with -mharden-sls=: ++ ++EnumValue ++Enum(harden_sls) String(none) Value(harden_sls_none) ++ ++EnumValue ++Enum(harden_sls) String(return) Value(harden_sls_return) ++ ++EnumValue ++Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch) ++ ++EnumValue ++Enum(harden_sls) String(all) Value(harden_sls_all) +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index 78ca7738df2..1e20efd6969 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -1284,7 +1284,7 @@ See RS/6000 and PowerPC Options. + -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol + -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol + -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol +--mindirect-branch-register} ++-mindirect-branch-register -mharden-sls=@var{choice}} + + @emph{x86 Windows Options} + @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol +@@ -28036,6 +28036,14 @@ not be reachable in the large code model. + @opindex -mindirect-branch-register + Force indirect call and jump via register. + ++@item -mharden-sls=@var{choice} ++@opindex mharden-sls ++Generate code to mitigate against straight line speculation (SLS) with ++@var{choice}. The default is @samp{none} which disables all SLS ++hardening. @samp{return} enables SLS hardening for function return. ++@samp{indirect-branch} enables SLS hardening for indirect branch. ++@samp{all} enables all SLS hardening. ++ + @end table + + These @samp{-m} switches are supported in addition to the above +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c +new file mode 100644 +index 00000000000..6f70dc94a23 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void foo (void); ++ ++void ++bar (void) ++{ ++ foo (); ++} ++ ++/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */ ++/* { dg-final { scan-assembler-not {int3} } } */ +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c +new file mode 100644 +index 00000000000..a7c59078d03 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void (*fptr) (void); ++ ++void ++foo (void) ++{ ++ fptr (); ++} ++ ++/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ ++/* { dg-final { scan-assembler-times "int3" 1 } } */ +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c +new file mode 100644 +index 00000000000..1a6056b6d7b +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c +@@ -0,0 +1,14 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void (*fptr) (void); ++ ++void ++foo (void) ++{ ++ fptr (); ++} ++ ++/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */ ++/* { dg-final { scan-assembler-times "int3" 2 } } */ +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c +new file mode 100644 +index 00000000000..f70dd1379d3 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c +@@ -0,0 +1,16 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void (*fptr) (void); ++ ++void ++foo (void) ++{ ++ fptr (); ++} ++ ++/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */ ++/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */ ++/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */ ++/* { dg-final { scan-assembler-times "int3" 1 } } */ +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c +new file mode 100644 +index 00000000000..613c44c6f82 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c +@@ -0,0 +1,17 @@ ++/* { dg-do compile } */ ++/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++typedef void (*dispatch_t)(long offset); ++ ++dispatch_t dispatch; ++ ++int ++male_indirect_jump (long offset) ++{ ++ dispatch(offset); ++ return 0; ++} ++ ++/* { dg-final { scan-assembler-times "ret" 1 } } */ ++/* { dg-final { scan-assembler-times "int3" 1 } } */ +-- +2.36.1 + diff --git a/gcc8-harden-2.patch b/gcc8-harden-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..669c11f779570197da1ffb027a77c3a397bc97d1 --- /dev/null +++ b/gcc8-harden-2.patch @@ -0,0 +1,155 @@ +From 0df8313a0a5d8533f2487e21d7b42e9adee28f18 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 27 Oct 2021 06:27:15 -0700 +Subject: [PATCH 2/4] x86: Add -mindirect-branch-cs-prefix + +Add -mindirect-branch-cs-prefix to add CS prefix to call and jmp to +indirect thunk with branch target in r8-r15 registers so that the call +and jmp instruction length is 6 bytes to allow them to be replaced with +"lfence; call *%r8-r15" or "lfence; jmp *%r8-r15" at run-time. + +gcc/ + + PR target/102952 + * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): Emit + CS prefix for -mindirect-branch-cs-prefix. + (ix86_output_indirect_branch_via_reg): Likewise. + * config/i386/i386.opt: Add -mindirect-branch-cs-prefix. + * doc/invoke.texi: Document -mindirect-branch-cs-prefix. + +gcc/testsuite/ + + PR target/102952 + * gcc.target/i386/indirect-thunk-cs-prefix-1.c: New test. + * gcc.target/i386/indirect-thunk-cs-prefix-2.c: Likewise. + +(cherry picked from commit 2196a681d7810ad8b227bf983f38ba716620545e) +--- + gcc/config/i386/i386.c | 14 ++++++++++++-- + gcc/config/i386/i386.opt | 4 ++++ + gcc/doc/invoke.texi | 10 +++++++++- + .../gcc.target/i386/indirect-thunk-cs-prefix-1.c | 14 ++++++++++++++ + .../gcc.target/i386/indirect-thunk-cs-prefix-2.c | 15 +++++++++++++++ + 5 files changed, 54 insertions(+), 3 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c + create mode 100644 gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c + +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index eb9303f8742..8442dd0daea 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -28728,7 +28728,12 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, + if (need_prefix == indirect_thunk_prefix_bnd) + fprintf (asm_out_file, "\tbnd jmp\t"); + else +- fprintf (asm_out_file, "\tjmp\t"); ++ { ++ if (REX_INT_REGNO_P (regno) ++ && ix86_indirect_branch_cs_prefix) ++ fprintf (asm_out_file, "\tcs\n"); ++ fprintf (asm_out_file, "\tjmp\t"); ++ } + assemble_name (asm_out_file, thunk_name); + putc ('\n', asm_out_file); + if ((ix86_harden_sls & harden_sls_indirect_branch)) +@@ -28787,7 +28792,12 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p) + if (need_prefix == indirect_thunk_prefix_bnd) + fprintf (asm_out_file, "\tbnd call\t"); + else +- fprintf (asm_out_file, "\tcall\t"); ++ { ++ if (REX_INT_REGNO_P (regno) ++ && ix86_indirect_branch_cs_prefix) ++ fprintf (asm_out_file, "\tcs\n"); ++ fprintf (asm_out_file, "\tcall\t"); ++ } + assemble_name (asm_out_file, thunk_name); + putc ('\n', asm_out_file); + return; +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt +index 3ae48609e25..9f67ef558dc 100644 +--- a/gcc/config/i386/i386.opt ++++ b/gcc/config/i386/i386.opt +@@ -1044,6 +1044,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline) + EnumValue + Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern) + ++mindirect-branch-cs-prefix ++Target Var(ix86_indirect_branch_cs_prefix) Init(0) ++Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers. ++ + mindirect-branch-register + Target Report Var(ix86_indirect_branch_register) Init(0) + Force indirect call and jump via register. +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index 1e20efd6969..605cd4b93f1 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -1284,7 +1284,8 @@ See RS/6000 and PowerPC Options. + -mstack-protector-guard-symbol=@var{symbol} -mmitigate-rop @gol + -mgeneral-regs-only -mcall-ms2sysv-xlogues @gol + -mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol +--mindirect-branch-register -mharden-sls=@var{choice}} ++-mindirect-branch-register -mharden-sls=@var{choice} @gol ++-mindirect-branch-cs-prefix} + + @emph{x86 Windows Options} + @gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol +@@ -28044,6 +28045,13 @@ hardening. @samp{return} enables SLS hardening for function return. + @samp{indirect-branch} enables SLS hardening for indirect branch. + @samp{all} enables all SLS hardening. + ++@item -mindirect-branch-cs-prefix ++@opindex mindirect-branch-cs-prefix ++Add CS prefix to call and jmp to indirect thunk with branch target in ++r8-r15 registers so that the call and jmp instruction length is 6 bytes ++to allow them to be replaced with @samp{lfence; call *%r8-r15} or ++@samp{lfence; jmp *%r8-r15} at run-time. ++ + @end table + + These @samp{-m} switches are supported in addition to the above +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c +new file mode 100644 +index 00000000000..db2f3416823 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c +@@ -0,0 +1,14 @@ ++/* { dg-do compile { target { ! ia32 } } } */ ++/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void (*fptr) (void); ++ ++void ++foo (void) ++{ ++ fptr (); ++} ++ ++/* { dg-final { scan-assembler-times "jmp\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */ ++/* { dg-final { scan-assembler-times "\tcs" 1 } } */ +diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c +new file mode 100644 +index 00000000000..adfc39a49d4 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c +@@ -0,0 +1,15 @@ ++/* { dg-do compile { target { ! ia32 } } } */ ++/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */ ++/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */ ++ ++extern void (*bar) (void); ++ ++int ++foo (void) ++{ ++ bar (); ++ return 0; ++} ++ ++/* { dg-final { scan-assembler-times "call\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */ ++/* { dg-final { scan-assembler-times "\tcs" 1 } } */ +-- +2.36.1 + diff --git a/gcc8-harden-3.patch b/gcc8-harden-3.patch new file mode 100644 index 0000000000000000000000000000000000000000..ecb643a3641f716b30b7c5a07db772a4e536a538 --- /dev/null +++ b/gcc8-harden-3.patch @@ -0,0 +1,108 @@ +From 621de498ee19e1f2642eebde707430254c0459c0 Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 5 Jan 2022 16:33:16 -0800 +Subject: [PATCH 3/4] x86: Rename -harden-sls=indirect-branch to + -harden-sls=indirect-jmp + +Indirect branch also includes indirect call instructions. Rename +-harden-sls=indirect-branch to -harden-sls=indirect-jmp to match its +intended behavior. + + PR target/102952 + * config/i386/i386-opts.h (harden_sls): Replace + harden_sls_indirect_branch with harden_sls_indirect_jmp. + * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): + Likewise. + (ix86_output_indirect_jmp): Likewise. + (ix86_output_call_insn): Likewise. + * config/i386/i386.opt: Replace indirect-branch with + indirect-jmp. Replace harden_sls_indirect_branch with + harden_sls_indirect_jmp. + * doc/invoke.texi (-harden-sls=): Replace indirect-branch with + indirect-jmp. + +(cherry picked from commit ed8060950c64f2e449aaf90e438aa26d0d9d0b31) +--- + gcc/config/i386/i386-opts.h | 4 ++-- + gcc/config/i386/i386.c | 6 +++--- + gcc/config/i386/i386.opt | 2 +- + gcc/doc/invoke.texi | 4 ++-- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h +index 34718b6d52c..47facc254cd 100644 +--- a/gcc/config/i386/i386-opts.h ++++ b/gcc/config/i386/i386-opts.h +@@ -122,8 +122,8 @@ enum indirect_branch { + enum harden_sls { + harden_sls_none = 0, + harden_sls_return = 1 << 0, +- harden_sls_indirect_branch = 1 << 1, +- harden_sls_all = harden_sls_return | harden_sls_indirect_branch ++ harden_sls_indirect_jmp = 1 << 1, ++ harden_sls_all = harden_sls_return | harden_sls_indirect_jmp + }; + + #endif +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 8442dd0daea..3bc14e20105 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -28736,7 +28736,7 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, + } + assemble_name (asm_out_file, thunk_name); + putc ('\n', asm_out_file); +- if ((ix86_harden_sls & harden_sls_indirect_branch)) ++ if ((ix86_harden_sls & harden_sls_indirect_jmp)) + fputs ("\tint3\n", asm_out_file); + } + else +@@ -28991,7 +28991,7 @@ ix86_output_indirect_jmp (rtx call_op) + } + else + output_asm_insn ("%!jmp\t%A0", &call_op); +- return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : ""; ++ return (ix86_harden_sls & harden_sls_indirect_jmp) ? "int3" : ""; + } + + /* Output function return. CALL_OP is the jump target. Add a REP +@@ -29178,7 +29178,7 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op) + { + output_asm_insn (xasm, &call_op); + if (!direct_p +- && (ix86_harden_sls & harden_sls_indirect_branch)) ++ && (ix86_harden_sls & harden_sls_indirect_jmp)) + return "int3"; + } + return ""; +diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt +index 9f67ef558dc..7a5c7b9369a 100644 +--- a/gcc/config/i386/i386.opt ++++ b/gcc/config/i386/i386.opt +@@ -1075,7 +1075,7 @@ EnumValue + Enum(harden_sls) String(return) Value(harden_sls_return) + + EnumValue +-Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch) ++Enum(harden_sls) String(indirect-jmp) Value(harden_sls_indirect_jmp) + + EnumValue + Enum(harden_sls) String(all) Value(harden_sls_all) +diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi +index 605cd4b93f1..20d8e3fd782 100644 +--- a/gcc/doc/invoke.texi ++++ b/gcc/doc/invoke.texi +@@ -28041,8 +28041,8 @@ Force indirect call and jump via register. + @opindex mharden-sls + Generate code to mitigate against straight line speculation (SLS) with + @var{choice}. The default is @samp{none} which disables all SLS +-hardening. @samp{return} enables SLS hardening for function return. +-@samp{indirect-branch} enables SLS hardening for indirect branch. ++hardening. @samp{return} enables SLS hardening for function returns. ++@samp{indirect-jmp} enables SLS hardening for indirect jumps. + @samp{all} enables all SLS hardening. + + @item -mindirect-branch-cs-prefix +-- +2.36.1 + diff --git a/gcc8-harden-4.patch b/gcc8-harden-4.patch new file mode 100644 index 0000000000000000000000000000000000000000..648d543863898ff75286325593efd05728fc2f82 --- /dev/null +++ b/gcc8-harden-4.patch @@ -0,0 +1,75 @@ +From 5a5e7890cefa112e95e1de9800d8081c2a38a1da Mon Sep 17 00:00:00 2001 +From: "H.J. Lu" +Date: Wed, 5 Jan 2022 18:04:21 -0800 +Subject: [PATCH 4/4] x86: Generate INT3 for __builtin_eh_return + +Generate INT3 after indirect jmp in exception return for -fcf-protection +with -mharden-sls=indirect-jmp. + +gcc/ + + PR target/103925 + * config/i386/i386.c (ix86_output_indirect_function_return): + Generate INT3 after indirect jmp for -mharden-sls=indirect-jmp. + +gcc/testsuite/ + + PR target/103925 + * gcc.target/i386/harden-sls-6.c: New test. + +(cherry picked from commit c2e5c4feed32c808591b5278f680bbabe63eb225) +--- + gcc/config/i386/i386.c | 9 ++++++--- + gcc/testsuite/gcc.target/i386/harden-sls-6.c | 18 ++++++++++++++++++ + 2 files changed, 24 insertions(+), 3 deletions(-) + create mode 100644 gcc/testsuite/gcc.target/i386/harden-sls-6.c + +diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c +index 3bc14e20105..dbc3d462fda 100644 +--- a/gcc/config/i386/i386.c ++++ b/gcc/config/i386/i386.c +@@ -29083,11 +29083,14 @@ ix86_output_indirect_function_return (rtx ret_op) + } + else + output_indirect_thunk (need_prefix, regno); +- +- return ""; + } + else +- return "%!jmp\t%A0"; ++ { ++ output_asm_insn ("%!jmp\t%A0", &ret_op); ++ if (ix86_harden_sls & harden_sls_indirect_jmp) ++ fputs ("\tint3\n", asm_out_file); ++ } ++ return ""; + } + + /* Split simple return with popping POPC bytes from stack to indirect +diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-6.c b/gcc/testsuite/gcc.target/i386/harden-sls-6.c +new file mode 100644 +index 00000000000..9068eb64008 +--- /dev/null ++++ b/gcc/testsuite/gcc.target/i386/harden-sls-6.c +@@ -0,0 +1,18 @@ ++/* { dg-do compile { target { ! ia32 } } } */ ++/* { dg-options "-O2 -fcf-protection -mharden-sls=indirect-jmp" } */ ++ ++struct _Unwind_Context _Unwind_Resume_or_Rethrow_this_context; ++ ++void offset (int); ++ ++struct _Unwind_Context { ++ void *reg[7]; ++} _Unwind_Resume_or_Rethrow() { ++ struct _Unwind_Context cur_contextcur_context = ++ _Unwind_Resume_or_Rethrow_this_context; ++ offset(0); ++ __builtin_eh_return ((long) offset, 0); ++} ++ ++/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rcx" } } */ ++/* { dg-final { scan-assembler-times "int3" 1 } } */ +-- +2.36.1 + diff --git a/gcc8-libstdc++-make_shared.patch b/gcc8-libstdc++-make_shared.patch new file mode 100644 index 0000000000000000000000000000000000000000..59256d831767d4e467ef0a2c7bf17ce458a4738e --- /dev/null +++ b/gcc8-libstdc++-make_shared.patch @@ -0,0 +1,61 @@ +commit 79fa567e234585dc6a71f9bd069101c993513f3e +Author: Jonathan Wakely +Date: Thu Apr 22 15:46:51 2021 +0100 + + libstdc++: Reject std::make_shared [PR 99006] + + Prior to C++20 it should be ill-formed to use std::make_shared with an + array type (and we don't support the C++20 feature to make it valid yet + anyway). + + libstdc++-v3/ChangeLog: + + PR libstdc++/99006 + * include/bits/shared_ptr.h (allocate_shared): Assert that _Tp + is not an array type. + * include/bits/shared_ptr_base.h (__allocate_shared): Likewise. + * testsuite/20_util/shared_ptr/creation/99006.cc: New test. + + (cherry picked from commit 55650236cd97d81f42f9fdb4f6bcb12babafe51f) + +diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h +index 281600b2901..4ddc52ae723 100644 +--- a/libstdc++-v3/include/bits/shared_ptr.h ++++ b/libstdc++-v3/include/bits/shared_ptr.h +@@ -698,6 +698,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + inline shared_ptr<_Tp> + allocate_shared(const _Alloc& __a, _Args&&... __args) + { ++ static_assert(!is_array<_Tp>::value, "make_shared not supported"); ++ + return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a}, + std::forward<_Args>(__args)...); + } +diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h +index 0367c2d51a5..8af6e9fb11c 100644 +--- a/libstdc++-v3/include/bits/shared_ptr_base.h ++++ b/libstdc++-v3/include/bits/shared_ptr_base.h +@@ -1822,6 +1822,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + inline __shared_ptr<_Tp, _Lp> + __allocate_shared(const _Alloc& __a, _Args&&... __args) + { ++ static_assert(!is_array<_Tp>::value, "make_shared not supported"); ++ + return __shared_ptr<_Tp, _Lp>(_Sp_alloc_shared_tag<_Alloc>{__a}, + std::forward<_Args>(__args)...); + } +diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc +new file mode 100644 +index 00000000000..d5f7a5da5e9 +--- /dev/null ++++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/99006.cc +@@ -0,0 +1,9 @@ ++// FIXME: This should use { target { ! c++20 } } ++// { dg-do compile } ++ ++#include ++ ++auto p = std::make_shared(2); // { dg-error "here" } ++auto q = std::make_shared(1, 2); // { dg-error "here" } ++ ++// { dg-prune-output "static assertion failed" } diff --git a/gcc8-pr105502.patch b/gcc8-pr105502.patch new file mode 100644 index 0000000000000000000000000000000000000000..7200b9d9896920e314f624bd9037bf35b7f12e20 --- /dev/null +++ b/gcc8-pr105502.patch @@ -0,0 +1,98 @@ +From b005000525ab0a5116d21217c41fb1da5bd03796 Mon Sep 17 00:00:00 2001 +From: Jonathan Wakely +Date: Fri, 6 May 2022 21:19:17 +0100 +Subject: [PATCH] libstdc++: Fix deserialization for std::normal_distribution + [PR105502] + +This fixes a regression in std::normal_distribution deserialization that +caused the object to be left unchanged if the __state_avail value read +from the stream was false. + +libstdc++-v3/ChangeLog: + + PR libstdc++/105502 + * include/bits/random.tcc + (operator>>(basic_istream&, normal_distribution&)): + Update state when __state_avail is false. + * testsuite/26_numerics/random/normal_distribution/operators/serialize.cc: + Check that deserialized object equals serialized one. + +(cherry picked from commit 909ef4e2727ddc50a32d6ad379a1f1ccc1043c6a) +--- + libstdc++-v3/include/bits/random.tcc | 2 +- + .../operators/serialize.cc | 36 ++++++++++++++++++- + 2 files changed, 36 insertions(+), 2 deletions(-) + +diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc +index 0a299baedc5..0f758671f69 100644 +--- a/libstdc++-v3/include/bits/random.tcc ++++ b/libstdc++-v3/include/bits/random.tcc +@@ -1941,7 +1941,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + bool __saved_avail; + if (__is >> __mean >> __stddev >> __saved_avail) + { +- if (__saved_avail && (__is >> __x._M_saved)) ++ if (!__saved_avail || (__is >> __x._M_saved)) + { + __x._M_saved_available = __saved_avail; + __x.param(typename normal_distribution<_RealType>:: +diff --git a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc +index a65d4004161..8cc70886bc7 100644 +--- a/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc ++++ b/libstdc++-v3/testsuite/26_numerics/random/normal_distribution/operators/serialize.cc +@@ -25,6 +25,7 @@ + + #include + #include ++#include + + void + test01() +@@ -37,10 +38,43 @@ test01() + str << u; + + str >> v; ++ VERIFY( u == v ); ++} ++ ++void ++test_pr105502() ++{ ++ // PR libstdc++/105502 std::normal_distribution deserialization issue ++ std::stringstream str; ++ std::normal_distribution<> d{1, 2}, d2; ++ std::minstd_rand0 g; ++ str << d; ++ VERIFY( str ); ++ str >> d2; ++ VERIFY( str ); ++ VERIFY( d == d2 ); ++ ++ (void) d(g); // sets d._M_saved_available = true ++ str.str(""); ++ str.clear(); ++ str << d; ++ VERIFY( str ); ++ str >> d2; ++ VERIFY( str ); ++ VERIFY( d == d2 ); ++ ++ (void) d(g); // sets d._M_saved_available = false ++ str.str(""); ++ str.clear(); ++ str << d; ++ VERIFY( str ); ++ str >> d2; ++ VERIFY( str ); ++ VERIFY( d == d2 ); + } + + int main() + { + test01(); +- return 0; ++ test_pr105502(); + } +-- +2.31.1 + diff --git a/gcc8-pr99536.patch b/gcc8-pr99536.patch new file mode 100644 index 0000000000000000000000000000000000000000..db6706e0665f8a5e7a8d4a38220f005f1ec7ac08 --- /dev/null +++ b/gcc8-pr99536.patch @@ -0,0 +1,47 @@ +commit 29dad307b5d7cfdb6626c11c8e43ebff941c950b +Author: Jonathan Wakely +Date: Thu Mar 11 16:43:51 2021 +0000 + + libstdc++: Initialize std::normal_distribution::_M_saved [PR 99536] + + This avoids a false positive -Wmaybe-uninitialized warning, by + initializing _M_saved on construction. + + libstdc++-v3/ChangeLog: + + PR libstdc++/99536 + * include/bits/random.h (normal_distribution): Use + default-initializer for _M_saved and _M_saved_available. + + (cherry picked from commit 67e397660611990efd98f9e4106c1ee81f6803a4) + +diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h +index b36781ed290..3385345d273 100644 +--- a/libstdc++-v3/include/bits/random.h ++++ b/libstdc++-v3/include/bits/random.h +@@ -1974,12 +1974,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + explicit + normal_distribution(result_type __mean = result_type(0), + result_type __stddev = result_type(1)) +- : _M_param(__mean, __stddev), _M_saved_available(false) ++ : _M_param(__mean, __stddev) + { } + + explicit + normal_distribution(const param_type& __p) +- : _M_param(__p), _M_saved_available(false) ++ : _M_param(__p) + { } + + /** +@@ -2158,8 +2158,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + const param_type& __p); + + param_type _M_param; +- result_type _M_saved; +- bool _M_saved_available; ++ result_type _M_saved = 0; ++ bool _M_saved_available = false; + }; + + /** diff --git a/gcc8-rh2001788.patch b/gcc8-rh2001788.patch new file mode 100644 index 0000000000000000000000000000000000000000..15f20be6958ece5d71fb9a174a3a7d38ff91cb51 --- /dev/null +++ b/gcc8-rh2001788.patch @@ -0,0 +1,456 @@ +commit ee3db7c8f844556d35a66b3732bad9f44a086491 +Author: Jonathan Wakely +Date: Mon Sep 27 20:44:24 2021 +0100 + + libstdc++: Fix handling of invalid ranges in std::regex [PR102447] + + std::regex currently allows invalid bracket ranges such as [\w-a] which + are only allowed by ECMAScript when in web browser compatibility mode. + It should be an error, because the start of the range is a character + class, not a single character. The current implementation of + _Compiler::_M_expression_term does not provide a way to reject this, + because we only remember a previous character, not whether we just + processed a character class (or collating symbol etc.) + + This patch replaces the pair used to emulate + optional with a custom class closer to pair. That + allows us to track three states, so that we can tell when we've just + seen a character class. + + With this additional state the code in _M_expression_term for processing + the _S_token_bracket_dash can be improved to correctly reject the [\w-a] + case, without regressing for valid cases such as [\w-] and [----]. + + libstdc++-v3/ChangeLog: + + PR libstdc++/102447 + * include/bits/regex_compiler.h (_Compiler::_BracketState): New + class. + (_Compiler::_BrackeyMatcher): New alias template. + (_Compiler::_M_expression_term): Change pair + parameter to _BracketState. Process first character for + ECMAScript syntax as well as POSIX. + * include/bits/regex_compiler.tcc + (_Compiler::_M_insert_bracket_matcher): Pass _BracketState. + (_Compiler::_M_expression_term): Use _BracketState to store + state between calls. Improve handling of dashes in ranges. + * testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc: + Add more tests for ranges containing dashes. Check invalid + ranges with character class at the beginning. + + (cherry picked from commit 7ce3c230edf6e498e125c805a6dd313bf87dc439) + +diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h +index 7e5c2073554..2eb1c3f7863 100644 +--- a/libstdc++-v3/include/bits/regex_compiler.h ++++ b/libstdc++-v3/include/bits/regex_compiler.h +@@ -122,13 +122,45 @@ namespace __detail + void + _M_insert_bracket_matcher(bool __neg); + +- // Returns true if successfully matched one term and should continue. ++ // Cache of the last atom seen in a bracketed range expression. ++ struct _BracketState ++ { ++ enum class _Type : char { _None, _Char, _Class } _M_type = _Type::_None; ++ _CharT _M_char; ++ ++ void ++ set(_CharT __c) noexcept { _M_type = _Type::_Char; _M_char = __c; } ++ ++ _GLIBCXX_NODISCARD _CharT ++ get() const noexcept { return _M_char; } ++ ++ void ++ reset(_Type __t = _Type::_None) noexcept { _M_type = __t; } ++ ++ explicit operator bool() const noexcept ++ { return _M_type != _Type::_None; } ++ ++ // Previous token was a single character. ++ _GLIBCXX_NODISCARD bool ++ _M_is_char() const noexcept { return _M_type == _Type::_Char; } ++ ++ // Previous token was a character class, equivalent class, ++ // collating symbol etc. ++ _GLIBCXX_NODISCARD bool ++ _M_is_class() const noexcept { return _M_type == _Type::_Class; } ++ }; ++ ++ template ++ using _BracketMatcher ++ = std::__detail::_BracketMatcher<_TraitsT, __icase, __collate>; ++ ++ // Returns true if successfully parsed one term and should continue ++ // compiling a bracket expression. + // Returns false if the compiler should move on. + template + bool +- _M_expression_term(pair& __last_char, +- _BracketMatcher<_TraitsT, __icase, __collate>& +- __matcher); ++ _M_expression_term(_BracketState& __last_char, ++ _BracketMatcher<__icase, __collate>& __matcher); + + int + _M_cur_int_value(int __radix); +diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc +index b1169428afb..5877d30ba52 100644 +--- a/libstdc++-v3/include/bits/regex_compiler.tcc ++++ b/libstdc++-v3/include/bits/regex_compiler.tcc +@@ -140,7 +140,8 @@ namespace __detail + return true; + if (this->_M_atom()) + { +- while (this->_M_quantifier()); ++ while (this->_M_quantifier()) ++ ; + return true; + } + return false; +@@ -410,7 +411,7 @@ namespace __detail + _M_insert_character_class_matcher() + { + __glibcxx_assert(_M_value.size() == 1); +- _BracketMatcher<_TraitsT, __icase, __collate> __matcher ++ _BracketMatcher<__icase, __collate> __matcher + (_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits); + __matcher._M_add_character_class(_M_value, false); + __matcher._M_ready(); +@@ -424,25 +425,17 @@ namespace __detail + _Compiler<_TraitsT>:: + _M_insert_bracket_matcher(bool __neg) + { +- _BracketMatcher<_TraitsT, __icase, __collate> __matcher(__neg, _M_traits); +- pair __last_char; // Optional<_CharT> +- __last_char.first = false; +- if (!(_M_flags & regex_constants::ECMAScript)) +- { +- if (_M_try_char()) +- { +- __last_char.first = true; +- __last_char.second = _M_value[0]; +- } +- else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) +- { +- __last_char.first = true; +- __last_char.second = '-'; +- } +- } +- while (_M_expression_term(__last_char, __matcher)); +- if (__last_char.first) +- __matcher._M_add_char(__last_char.second); ++ _BracketMatcher<__icase, __collate> __matcher(__neg, _M_traits); ++ _BracketState __last_char; ++ if (_M_try_char()) ++ __last_char.set(_M_value[0]); ++ else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) ++ // Dash as first character is a normal character. ++ __last_char.set('-'); ++ while (_M_expression_term(__last_char, __matcher)) ++ ; ++ if (__last_char._M_is_char()) ++ __matcher._M_add_char(__last_char.get()); + __matcher._M_ready(); + _M_stack.push(_StateSeqT( + *_M_nfa, +@@ -453,27 +446,27 @@ namespace __detail + template + bool + _Compiler<_TraitsT>:: +- _M_expression_term(pair& __last_char, +- _BracketMatcher<_TraitsT, __icase, __collate>& __matcher) ++ _M_expression_term(_BracketState& __last_char, ++ _BracketMatcher<__icase, __collate>& __matcher) + { + if (_M_match_token(_ScannerT::_S_token_bracket_end)) + return false; + ++ // Add any previously cached char into the matcher and update cache. + const auto __push_char = [&](_CharT __ch) + { +- if (__last_char.first) +- __matcher._M_add_char(__last_char.second); +- else +- __last_char.first = true; +- __last_char.second = __ch; ++ if (__last_char._M_is_char()) ++ __matcher._M_add_char(__last_char.get()); ++ __last_char.set(__ch); + }; +- const auto __flush = [&] ++ // Add any previously cached char into the matcher and update cache. ++ const auto __push_class = [&] + { +- if (__last_char.first) +- { +- __matcher._M_add_char(__last_char.second); +- __last_char.first = false; +- } ++ if (__last_char._M_is_char()) ++ __matcher._M_add_char(__last_char.get()); ++ // We don't cache anything here, just record that the last thing ++ // processed was a character class (or similar). ++ __last_char.reset(_BracketState::_Type::_Class); + }; + + if (_M_match_token(_ScannerT::_S_token_collsymbol)) +@@ -482,16 +475,16 @@ namespace __detail + if (__symbol.size() == 1) + __push_char(__symbol[0]); + else +- __flush(); ++ __push_class(); + } + else if (_M_match_token(_ScannerT::_S_token_equiv_class_name)) + { +- __flush(); ++ __push_class(); + __matcher._M_add_equivalence_class(_M_value); + } + else if (_M_match_token(_ScannerT::_S_token_char_class_name)) + { +- __flush(); ++ __push_class(); + __matcher._M_add_character_class(_M_value, false); + } + else if (_M_try_char()) +@@ -508,49 +501,50 @@ namespace __detail + // It turns out that no one reads BNFs ;) + else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) + { +- if (!__last_char.first) ++ if (_M_match_token(_ScannerT::_S_token_bracket_end)) + { +- if (!(_M_flags & regex_constants::ECMAScript)) +- { +- if (_M_match_token(_ScannerT::_S_token_bracket_end)) +- { +- __push_char('-'); +- return false; +- } +- __throw_regex_error( +- regex_constants::error_range, +- "Unexpected dash in bracket expression. For POSIX syntax, " +- "a dash is not treated literally only when it is at " +- "beginning or end."); +- } ++ // For "-]" the dash is a literal character. + __push_char('-'); ++ return false; + } +- else ++ else if (__last_char._M_is_class()) ++ { ++ // "\\w-" is invalid, start of range must be a single char. ++ __throw_regex_error(regex_constants::error_range, ++ "Invalid start of range in bracket expression."); ++ } ++ else if (__last_char._M_is_char()) + { + if (_M_try_char()) + { +- __matcher._M_make_range(__last_char.second, _M_value[0]); +- __last_char.first = false; ++ // "x-y" ++ __matcher._M_make_range(__last_char.get(), _M_value[0]); ++ __last_char.reset(); + } + else if (_M_match_token(_ScannerT::_S_token_bracket_dash)) + { +- __matcher._M_make_range(__last_char.second, '-'); +- __last_char.first = false; ++ // "x--" ++ __matcher._M_make_range(__last_char.get(), '-'); ++ __last_char.reset(); + } + else +- { +- if (_M_scanner._M_get_token() +- != _ScannerT::_S_token_bracket_end) +- __throw_regex_error( +- regex_constants::error_range, +- "Character is expected after a dash."); +- __push_char('-'); +- } ++ __throw_regex_error(regex_constants::error_range, ++ "Invalid end of range in bracket expression."); + } ++ else if (_M_flags & regex_constants::ECMAScript) ++ { ++ // A dash that is not part of an existing range. Might be the ++ // start of a new range, or might just be a literal '-' char. ++ // Only ECMAScript allows that in the middle of a bracket expr. ++ __push_char('-'); ++ } ++ else ++ __throw_regex_error(regex_constants::error_range, ++ "Invalid dash in bracket expression."); + } + else if (_M_match_token(_ScannerT::_S_token_quoted_class)) + { +- __flush(); ++ __push_class(); + __matcher._M_add_character_class(_M_value, + _M_ctype.is(_CtypeT::upper, + _M_value[0])); +diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc +index 236ab663fc0..57088f5af83 100644 +--- a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc ++++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/cstring_bracket_01.cc +@@ -68,6 +68,16 @@ test01() + void + test02() + { ++ VERIFY(regex_match("-", regex("[-]", regex_constants::ECMAScript))); ++ VERIFY(regex_match("-", regex("[--]", regex_constants::ECMAScript))); ++ VERIFY(regex_match("-", regex("[---]", regex_constants::ECMAScript))); ++ VERIFY(regex_match("-", regex("[----]", regex_constants::ECMAScript))); ++ VERIFY(regex_match("-", regex("[-----]", regex_constants::ECMAScript))); ++ ++ VERIFY(regex_match("-", regex("[-]", regex_constants::extended))); ++ VERIFY(regex_match("-", regex("[--]", regex_constants::extended))); ++ VERIFY(regex_match("-", regex("[---]", regex_constants::extended))); ++ VERIFY(regex_match("-", regex("[----]", regex_constants::extended))); + try + { + std::regex re("[-----]", std::regex::extended); +@@ -77,7 +87,6 @@ test02() + { + VERIFY(e.code() == std::regex_constants::error_range); + } +- std::regex re("[-----]", std::regex::ECMAScript); + + VERIFY(!regex_match("b", regex("[-ac]", regex_constants::extended))); + VERIFY(!regex_match("b", regex("[ac-]", regex_constants::extended))); +@@ -92,7 +101,27 @@ test02() + } + catch (const std::regex_error& e) + { ++ VERIFY(e.code() == std::regex_constants::error_range); ++ } ++ try ++ { ++ regex("[@--]", regex_constants::extended); ++ VERIFY(false); + } ++ catch (const std::regex_error& e) ++ { ++ VERIFY(e.code() == std::regex_constants::error_range); ++ } ++ try ++ { ++ regex("[--%]", regex_constants::extended); ++ VERIFY(false); ++ } ++ catch (const std::regex_error& e) ++ { ++ VERIFY(e.code() == std::regex_constants::error_range); ++ } ++ + VERIFY(regex_match("].", regex("[][.hyphen.]-0]*", regex_constants::extended))); + } + +@@ -157,6 +186,36 @@ test06() + VERIFY(regex_match("a-", debian_cron_namespace_ok)); + } + ++// libstdc++/102447 ++void ++test07() ++{ ++ VERIFY(regex_match("-", std::regex("[\\w-]", std::regex::ECMAScript))); ++ VERIFY(regex_match("a", std::regex("[\\w-]", std::regex::ECMAScript))); ++ VERIFY(regex_match("-", std::regex("[a-]", std::regex::ECMAScript))); ++ VERIFY(regex_match("a", std::regex("[a-]", std::regex::ECMAScript))); ++ ++ try ++ { ++ std::regex re("[\\w-a]", std::regex::ECMAScript); ++ VERIFY(false); ++ } ++ catch (const std::regex_error& e) ++ { ++ VERIFY(e.code() == std::regex_constants::error_range); ++ } ++ ++ try ++ { ++ std::regex re("[\\w--]", std::regex::ECMAScript); ++ VERIFY(false); ++ } ++ catch (const std::regex_error& e) ++ { ++ VERIFY(e.code() == std::regex_constants::error_range); ++ } ++} ++ + int + main() + { +@@ -166,6 +225,7 @@ main() + test04(); + test05(); + test06(); ++ test07(); + + return 0; + } + +commit 1851cc4c5f2666dfdec53a2ada57095ffc59e08b +Author: Jonathan Wakely +Date: Mon Dec 13 13:36:33 2021 +0000 + + libstdc++: Fix non-reserved name in header + + libstdc++-v3/ChangeLog: + + * include/bits/regex_compiler.tcc (_Compiler::_M_match_token): + Use reserved name for parameter. + * testsuite/17_intro/names.cc: Check "token". + + (cherry picked from commit b0e6a257f1862e217cdf19332ea0f7bad56dcddc) + +diff --git a/libstdc++-v3/include/bits/regex_compiler.tcc b/libstdc++-v3/include/bits/regex_compiler.tcc +index 8af920e5fe9..b1169428afb 100644 +--- a/libstdc++-v3/include/bits/regex_compiler.tcc ++++ b/libstdc++-v3/include/bits/regex_compiler.tcc +@@ -586,9 +586,9 @@ namespace __detail + template + bool + _Compiler<_TraitsT>:: +- _M_match_token(_TokenT token) ++ _M_match_token(_TokenT __token) + { +- if (token == _M_scanner._M_get_token()) ++ if (__token == _M_scanner._M_get_token()) + { + _M_value = _M_scanner._M_get_value(); + _M_scanner._M_advance(); +diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc +index d758138dfb1..6c06aba7228 100644 +--- a/libstdc++-v3/testsuite/17_intro/names.cc ++++ b/libstdc++-v3/testsuite/17_intro/names.cc +@@ -99,6 +99,7 @@ + #define z ( + + #define tmp ( ++#define token ( + + #if __cplusplus < 201103L + #define uses_allocator ( +--- a/libstdc++-v3/include/bits/c++config.orig 2022-07-08 15:06:14.083231445 -0400 ++++ b/libstdc++-v3/include/bits/c++config 2022-07-08 15:06:41.733247859 -0400 +@@ -99,6 +99,12 @@ + # define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) + #endif + ++// Macro to warn about unused results. ++#if __cplusplus >= 201703L ++# define _GLIBCXX_NODISCARD [[__nodiscard__]] ++#else ++# define _GLIBCXX_NODISCARD ++#endif + + #if __cplusplus + diff --git a/gcc8-rh2117838.patch b/gcc8-rh2117838.patch new file mode 100644 index 0000000000000000000000000000000000000000..1b35e7d510ef5f0c7cc1a3e9bb44d45399da1c05 --- /dev/null +++ b/gcc8-rh2117838.patch @@ -0,0 +1,103 @@ +diff --git a/gcc/testsuite/g++.dg/torture/phi-1.C b/gcc/testsuite/g++.dg/torture/phi-1.C +new file mode 100644 +index 00000000000..69fb3d7ba38 +--- /dev/null ++++ b/gcc/testsuite/g++.dg/torture/phi-1.C +@@ -0,0 +1,28 @@ ++// { dg-do compile { target c++11 } } ++// { dg-options "--param early-inlining-insns=14" } ++ ++struct Element; ++template struct __array_traits { typedef Element _Type[_Nm]; }; ++template struct array { ++ typename __array_traits<_Nm>::_Type _M_elems; ++}; ++bool logLevel(); ++struct LogCapture { ++ void stream(); ++}; ++struct Element { ++ Element(); ++ long data_; ++}; ++using ElementArray = array<6>; ++struct ElementManager { ++ ElementManager(); ++ ElementArray array_; ++}; ++static ElementArray makeArray() { ++ if (logLevel()) ++ LogCapture().stream(); ++ ElementArray foo; ++ return foo; ++} ++ElementManager::ElementManager() : array_(makeArray()) {} +diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c +index 84e58e66628..78c0c6a4189 100644 +--- a/gcc/tree-cfg.c ++++ b/gcc/tree-cfg.c +@@ -2944,35 +2944,6 @@ last_and_only_stmt (basic_block bb) + return NULL; + } + +-/* Reinstall those PHI arguments queued in OLD_EDGE to NEW_EDGE. */ +- +-static void +-reinstall_phi_args (edge new_edge, edge old_edge) +-{ +- edge_var_map *vm; +- int i; +- gphi_iterator phis; +- +- vec *v = redirect_edge_var_map_vector (old_edge); +- if (!v) +- return; +- +- for (i = 0, phis = gsi_start_phis (new_edge->dest); +- v->iterate (i, &vm) && !gsi_end_p (phis); +- i++, gsi_next (&phis)) +- { +- gphi *phi = phis.phi (); +- tree result = redirect_edge_var_map_result (vm); +- tree arg = redirect_edge_var_map_def (vm); +- +- gcc_assert (result == gimple_phi_result (phi)); +- +- add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm)); +- } +- +- redirect_edge_var_map_clear (old_edge); +-} +- + /* Returns the basic block after which the new basic block created + by splitting edge EDGE_IN should be placed. Tries to keep the new block + near its "logical" location. This is of most help to humans looking +@@ -3012,11 +2983,24 @@ gimple_split_edge (edge edge_in) + new_bb = create_empty_bb (after_bb); + new_bb->count = edge_in->count (); + +- e = redirect_edge_and_branch (edge_in, new_bb); +- gcc_assert (e == edge_in); +- ++ /* We want to avoid re-allocating PHIs when we first ++ add the fallthru edge from new_bb to dest but we also ++ want to avoid changing PHI argument order when ++ first redirecting edge_in away from dest. The former ++ avoids changing PHI argument order by adding them ++ last and then the redirection swapping it back into ++ place by means of unordered remove. ++ So hack around things by temporarily removing all PHIs ++ from the destination during the edge redirection and then ++ making sure the edges stay in order. */ ++ gimple_seq saved_phis = phi_nodes (dest); ++ unsigned old_dest_idx = edge_in->dest_idx; ++ set_phi_nodes (dest, NULL); + new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU); +- reinstall_phi_args (new_edge, e); ++ e = redirect_edge_and_branch (edge_in, new_bb); ++ gcc_assert (e == edge_in && new_edge->dest_idx == old_dest_idx); ++ /* set_phi_nodes sets the BB of the PHI nodes, so do it manually here. */ ++ dest->il.gimple.phi_nodes = saved_phis; + + return new_bb; + } diff --git a/gcc8-rh2137448.patch b/gcc8-rh2137448.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c743822f77f6990822d6b64583d0f1efb2acb88 --- /dev/null +++ b/gcc8-rh2137448.patch @@ -0,0 +1,110 @@ +commit 8b89515caca5149329c0cd20485e69e2d0f879d4 +Author: Marek Polacek +Date: Wed Dec 7 13:44:38 2022 -0500 + + strlen: Use D_S_U in maybe_set_strlen_range + + This patch fixes #2137448 where the customer uses strlen on a buffer + that was filled by converting the buffer to a struct and copying a string + into a flexible array member of the struct. + + This regressed with r262438 in the sense that the strlen was folded to 0. + The strlen=0 result started with + https://gcc.gnu.org/pipermail/gcc-patches/2018-July/501912.html + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=715fcd73b66c639d9e0e3f3ef9c6ff9d621d7131 + which seems like an undesirable change. It was fixed (back to strlen=3) by + https://gcc.gnu.org/legacy-ml/gcc-patches/2019-01/msg00069.html + https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=d4bf69750d31d08068f8242225b8fa06cdf11411 + but the changes are not backportable. + + Instead, this patch makes maybe_set_strlen_range use DECL_SIZE_UNIT + rather than TYPE_SIZE_UNIT, fixing the regression. + + I could never reproduce the problem in C, only C++. C/C++ represent array + type domains differently: C has + + char[0:] + + but C++ + + char[0:18446744073709551615] + + I'm not sure if that explains it. In any case, I put the new test into + c-c++-common/. + + Also, the original test had + + printf("strlen = %zu\n", strlen(q->name)); + + so naturally, for the testsuite, I wanted to convert that into + + if (strlen(q->name) != ...) + __builtin_abort (); + + but then I could no longer reproduce the problem. After some poking + I realized I want -fno-early-inlining. + + Co-authored-by: Jakub Jelinek + +diff --git a/gcc/testsuite/c-c++-common/torture/strlenopt-1.c b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c +new file mode 100644 +index 00000000000..e8c11044119 +--- /dev/null ++++ b/gcc/testsuite/c-c++-common/torture/strlenopt-1.c +@@ -0,0 +1,38 @@ ++/* { dg-do run } */ ++/* { dg-options "-fno-early-inlining" } */ ++ ++#define FORTIFY_SOURCE 2 ++ ++struct S { ++ char skip; ++ char name[0]; ++}; ++ ++static char static_buf[4]; ++ ++static void ++print_name_len(void *p) ++{ ++ struct S *q = (struct S *) p; ++ if (__builtin_strlen(q->name) != 2) ++ __builtin_abort (); ++} ++ ++int ++main(void) ++{ ++ // treat static storage as struct ++ struct S *c = (struct S *)static_buf; ++ __builtin_strcpy(c->name, "aa"); ++ ++ // copy static storage to stack storage ++ char stack_buf[4] = { 0 }; ++ __builtin_memcpy(stack_buf, static_buf, 4); ++ ++ // static and stack both now contain ( 0, 'a', 'a', 0 } ++ ++ // indirectly pass the stack storage to the length function ++ char *s = (char *)stack_buf; ++ print_name_len(s); ++ return 0; ++} +diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c +index 55e82e7b638..da47046cc2a 100644 +--- a/gcc/tree-ssa-strlen.c ++++ b/gcc/tree-ssa-strlen.c +@@ -1200,8 +1200,11 @@ maybe_set_strlen_range (tree lhs, tree src) + || array_at_struct_end_p (src)) + return; + +- tree type = TREE_TYPE (src); +- if (tree size = TYPE_SIZE_UNIT (type)) ++ src = get_base_address (src); ++ if (!DECL_P (src)) ++ return; ++ ++ if (tree size = DECL_SIZE_UNIT (src)) + if (size && TREE_CODE (size) == INTEGER_CST) + { + wide_int max = wi::to_wide (size);