summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.OE-Core10
-rw-r--r--bitbake/lib/bb/process.py2
-rw-r--r--bitbake/lib/bb/server/process.py3
-rw-r--r--bitbake/lib/bb/server/xmlrpcserver.py1
-rw-r--r--bitbake/lib/bb/tests/fetch.py5
-rw-r--r--bitbake/lib/bb/utils.py13
-rw-r--r--bitbake/lib/toaster/orm/fixtures/oe-core.xml12
-rw-r--r--bitbake/lib/toaster/orm/fixtures/poky.xml18
-rw-r--r--bitbake/lib/toaster/orm/fixtures/settings.xml2
-rw-r--r--bitbake/lib/toaster/orm/models.py2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/projectconf.html16
-rw-r--r--documentation/bsp-guide/bsp.rst6
-rw-r--r--documentation/conf.py23
-rw-r--r--documentation/overview-manual/yp-intro.rst2
-rw-r--r--documentation/poky.yaml10
-rw-r--r--documentation/ref-manual/system-requirements.rst2
-rw-r--r--documentation/ref-manual/tasks.rst19
-rw-r--r--documentation/releases.rst36
-rw-r--r--documentation/sphinx-static/switchers.js8
-rw-r--r--meta-poky/conf/distro/include/gcsections.inc2
-rw-r--r--meta-poky/conf/distro/poky.conf4
-rw-r--r--meta-selftest/recipes-test/gitrepotest/gitrepotest.bb16
-rw-r--r--meta-selftest/recipes-test/gitrepotest/gitrepotest/0001-testpatch.patch9
-rw-r--r--meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.10.bbappend8
-rw-r--r--meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.4.bbappend8
-rw-r--r--meta/classes/buildhistory.bbclass30
-rw-r--r--meta/classes/cve-check.bbclass2
-rw-r--r--meta/classes/populate_sdk_base.bbclass11
-rw-r--r--meta/classes/rootfs-postcommands.bbclass2
-rw-r--r--meta/classes/sanity.bbclass2
-rw-r--r--meta/classes/sstate.bbclass16
-rw-r--r--meta/classes/toaster.bbclass8
-rw-r--r--meta/classes/uboot-sign.bbclass16
-rw-r--r--meta/classes/uninative.bbclass2
-rw-r--r--meta/conf/distro/include/cve-extra-exclusions.inc9
-rw-r--r--meta/conf/distro/include/default-distrovars.inc2
-rw-r--r--meta/conf/distro/include/maintainers.inc2
-rw-r--r--meta/conf/distro/include/yocto-uninative.inc11
-rw-r--r--meta/conf/machine/include/arm/arch-armv8-5a.inc19
-rw-r--r--meta/conf/machine/include/arm/armv9a/tune-neoversen2.inc22
-rw-r--r--meta/conf/machine/include/tune-cortexa72.inc12
-rw-r--r--meta/files/toolchain-shar-relocate.sh2
-rw-r--r--meta/lib/oe/patch.py21
-rw-r--r--meta/lib/oe/reproducible.py2
-rw-r--r--meta/lib/oe/sdk.py4
-rw-r--r--meta/lib/oeqa/runtime/cases/parselogs.py14
-rw-r--r--meta/lib/oeqa/selftest/cases/bbtests.py31
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py5
-rw-r--r--meta/lib/oeqa/selftest/cases/recipetool.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/reproducible.py10
-rw-r--r--meta/lib/oeqa/selftest/cases/runtime_test.py7
-rw-r--r--meta/recipes-bsp/grub/files/CVE-2021-3981-grub-mkconfig-Restore-umask-for-the-grub.cfg.patch49
-rw-r--r--meta/recipes-bsp/grub/grub2.inc1
-rw-r--r--meta/recipes-connectivity/mobile-broadband-provider-info/mobile-broadband-provider-info_git.bb7
-rw-r--r--meta/recipes-connectivity/openssl/openssl/reproducibility.patch22
-rw-r--r--meta/recipes-connectivity/openssl/openssl_1.1.1n.bb (renamed from meta/recipes-connectivity/openssl/openssl_1.1.1l.bb)4
-rw-r--r--meta/recipes-connectivity/socat/socat_1.7.4.1.bb2
-rw-r--r--meta/recipes-core/busybox/busybox-inittab_1.33.2.bb (renamed from meta/recipes-core/busybox/busybox-inittab_1.33.0.bb)0
-rw-r--r--meta/recipes-core/busybox/busybox/0001-awk-fix-CVEs.patch3266
-rw-r--r--meta/recipes-core/busybox/busybox/0002-man-fix-segfault-in-man-1.patch30
-rw-r--r--meta/recipes-core/busybox/busybox_1.33.2.bb (renamed from meta/recipes-core/busybox/busybox_1.33.1.bb)4
-rw-r--r--meta/recipes-core/expat/expat/CVE-2021-45960.patch65
-rw-r--r--meta/recipes-core/expat/expat/CVE-2021-46143.patch49
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-22822-27.patch257
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-23852.patch33
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-23990.patch49
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25235.patch261
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25236-1.patch116
-rw-r--r--meta/recipes-core/expat/expat/CVE-2022-25236-2.patch232
-rw-r--r--meta/recipes-core/expat/expat_2.2.10.bb14
-rw-r--r--meta/recipes-core/glibc/glibc-version.inc2
-rw-r--r--meta/recipes-core/glibc/glibc_2.33.bb2
-rw-r--r--meta/recipes-core/images/build-appliance-image_15.0.0.bb2
-rwxr-xr-xmeta/recipes-core/initrdscripts/initramfs-framework/finish12
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch99
-rw-r--r--meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch209
-rw-r--r--meta/recipes-core/libxml/libxml2_2.9.10.bb2
-rw-r--r--meta/recipes-core/os-release/os-release.bb4
-rw-r--r--meta/recipes-core/zlib/zlib/CVE-2018-25032.patch347
-rw-r--r--meta/recipes-core/zlib/zlib_1.2.11.bb1
-rw-r--r--meta/recipes-devtools/binutils/binutils-2.36.inc7
-rw-r--r--meta/recipes-devtools/binutils/binutils/0001-CVE-2021-20197.patch201
-rw-r--r--meta/recipes-devtools/binutils/binutils/0001-CVE-2021-42574.patch2006
-rw-r--r--meta/recipes-devtools/binutils/binutils/0001-CVE-2021-45078.patch255
-rw-r--r--meta/recipes-devtools/binutils/binutils/0002-CVE-2021-20197.patch170
-rw-r--r--meta/recipes-devtools/binutils/binutils/0003-CVE-2021-20197.patch171
-rw-r--r--meta/recipes-devtools/ccache/ccache_4.2.1.bb (renamed from meta/recipes-devtools/ccache/ccache_4.2.bb)4
-rw-r--r--meta/recipes-devtools/e2fsprogs/e2fsprogs.inc3
-rw-r--r--meta/recipes-devtools/e2fsprogs/e2fsprogs/0001-e2fsck-fix-last-mount-write-time-when-e2fsck-is-forc.patch66
-rw-r--r--meta/recipes-devtools/gcc/gcc-10.3.inc (renamed from meta/recipes-devtools/gcc/gcc-10.2.inc)18
-rw-r--r--meta/recipes-devtools/gcc/gcc-cross-canadian_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-cross-canadian_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-cross_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-cross_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-crosssdk_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-crosssdk_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-runtime_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-runtime_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-sanitizers_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-sanitizers_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc-source_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc-source_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/gcc/0001-CVE-2021-35465.patch22
-rw-r--r--meta/recipes-devtools/gcc/gcc/0001-CVE-2021-42574.patch2906
-rw-r--r--meta/recipes-devtools/gcc/gcc/0001-aarch64-Fix-up-__aarch64_cas16_acq_rel-fallback.patch66
-rw-r--r--meta/recipes-devtools/gcc/gcc/0001-aarch64-New-Straight-Line-Speculation-SLS-mitigation.patch202
-rw-r--r--meta/recipes-devtools/gcc/gcc/0002-CVE-2021-42574.patch2270
-rw-r--r--meta/recipes-devtools/gcc/gcc/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch607
-rw-r--r--meta/recipes-devtools/gcc/gcc/0003-CVE-2021-42574.patch1724
-rw-r--r--meta/recipes-devtools/gcc/gcc/0003-aarch64-Mitigate-SLS-for-BLR-instruction.patch658
-rw-r--r--meta/recipes-devtools/gcc/gcc/0004-CVE-2021-42574.patch138
-rw-r--r--meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch575
-rw-r--r--meta/recipes-devtools/gcc/gcc/0012-gcc-Fix-argument-list-too-long-error.patch5
-rw-r--r--meta/recipes-devtools/gcc/gcc/0033-Re-introduce-spe-commandline-options.patch2
-rw-r--r--meta/recipes-devtools/gcc/gcc/0036-mingw32-Enable-operation_not_supported.patch4
-rw-r--r--meta/recipes-devtools/gcc/gcc_10.3.bb (renamed from meta/recipes-devtools/gcc/gcc_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgcc-initial_10.3.bb (renamed from meta/recipes-devtools/gcc/libgcc-initial_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgcc_10.3.bb (renamed from meta/recipes-devtools/gcc/libgcc_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gcc/libgfortran_10.3.bb (renamed from meta/recipes-devtools/gcc/libgfortran_10.2.bb)0
-rw-r--r--meta/recipes-devtools/gnu-config/gnu-config_git.bb2
-rw-r--r--meta/recipes-devtools/go/go-1.16.15.inc (renamed from meta/recipes-devtools/go/go-1.16.8.inc)6
-rw-r--r--meta/recipes-devtools/go/go-binary-native_1.16.15.bb (renamed from meta/recipes-devtools/go/go-binary-native_1.16.8.bb)4
-rw-r--r--meta/recipes-devtools/go/go-cross-canadian_1.16.15.bb (renamed from meta/recipes-devtools/go/go-cross-canadian_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/go/go-cross_1.16.15.bb (renamed from meta/recipes-devtools/go/go-cross_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/go/go-crosssdk_1.16.15.bb (renamed from meta/recipes-devtools/go/go-crosssdk_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/go/go-native_1.16.15.bb (renamed from meta/recipes-devtools/go/go-native_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/go/go-runtime_1.16.15.bb (renamed from meta/recipes-devtools/go/go-runtime_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/go/go_1.16.15.bb (renamed from meta/recipes-devtools/go/go_1.16.8.bb)0
-rw-r--r--meta/recipes-devtools/patchelf/patchelf/0001-merge-from-PR243.patch47
-rw-r--r--meta/recipes-devtools/patchelf/patchelf_0.12.bb1
-rw-r--r--meta/recipes-devtools/python-numpy/files/CVE-2021-41496.patch64
-rw-r--r--meta/recipes-devtools/python-numpy/python3-numpy_1.20.1.bb1
-rw-r--r--meta/recipes-devtools/python/python3-pyelftools_0.27.bb2
-rw-r--r--meta/recipes-devtools/python/python3/0001-Makefile-fix-Issue36464-parallel-build-race-problem.patch34
-rw-r--r--meta/recipes-devtools/python/python3/0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch20
-rw-r--r--meta/recipes-devtools/python/python3_3.9.9.bb (renamed from meta/recipes-devtools/python/python3_3.9.5.bb)3
-rw-r--r--meta/recipes-devtools/qemu/qemu.inc5
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2021-20196_1.patch54
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2021-20196_2.patch67
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2021-3713.patch68
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2021-3748.patch127
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2021-3930.patch53
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2021-31799.patch57
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2021-31810.patch258
-rw-r--r--meta/recipes-devtools/ruby/ruby/CVE-2021-32066.patch102
-rw-r--r--meta/recipes-devtools/ruby/ruby_3.0.3.bb (renamed from meta/recipes-devtools/ruby/ruby_3.0.1.bb)7
-rw-r--r--meta/recipes-devtools/unfs3/unfs3_git.bb2
-rw-r--r--meta/recipes-extended/asciidoc/asciidoc_9.1.0.bb2
-rw-r--r--meta/recipes-extended/cups/cups.inc2
-rw-r--r--meta/recipes-extended/ghostscript/ghostscript/CVE-2021-45949.patch65
-rw-r--r--meta/recipes-extended/ghostscript/ghostscript/check-stack-limits-after-function-evalution.patch51
-rw-r--r--meta/recipes-extended/ghostscript/ghostscript_9.53.3.bb2
-rw-r--r--meta/recipes-extended/libarchive/libarchive_3.5.3.bb (renamed from meta/recipes-extended/libarchive/libarchive_3.5.1.bb)2
-rw-r--r--meta/recipes-extended/lighttpd/lighttpd/0001-mod_extforward-fix-out-of-bounds-OOB-write-fixes-313.patch97
-rw-r--r--meta/recipes-extended/lighttpd/lighttpd_1.4.59.bb1
-rw-r--r--meta/recipes-extended/mc/files/0001-Ticket-4200-fix-FTBFS-with-ncurses-build-with-disabl.patch87
-rw-r--r--meta/recipes-extended/mc/mc_4.8.26.bb5
-rw-r--r--meta/recipes-extended/pigz/files/0001-Fix-bug-when-combining-l-with-d.patch50
-rw-r--r--meta/recipes-extended/pigz/pigz_2.6.bb3
-rw-r--r--meta/recipes-extended/zip/zip-3.0/0001-configure-use-correct-CPP.patch47
-rw-r--r--meta/recipes-extended/zip/zip-3.0/0002-configure-support-PIC-code-build.patch34
-rw-r--r--meta/recipes-extended/zip/zip_3.0.bb2
-rw-r--r--meta/recipes-gnome/epiphany/epiphany_3.38.2.bb1
-rw-r--r--meta/recipes-gnome/epiphany/files/encode-untrusted-data.patch707
-rw-r--r--meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0135.patch117
-rw-r--r--meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0175.patch112
-rw-r--r--meta/recipes-graphics/virglrenderer/virglrenderer_0.8.2.bb4
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg.inc10
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4008.patch59
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4009.patch50
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4010.patch39
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4011.patch40
-rw-r--r--meta/recipes-graphics/xorg-xserver/xserver-xorg_1.20.10.bb4
-rw-r--r--meta/recipes-kernel/linux-firmware/linux-firmware_20220310.bb (renamed from meta/recipes-kernel/linux-firmware/linux-firmware_20211027.bb)7
-rw-r--r--meta/recipes-kernel/linux/linux-yocto-rt_5.10.bb6
-rw-r--r--meta/recipes-kernel/linux/linux-yocto-rt_5.4.bb6
-rw-r--r--meta/recipes-kernel/linux/linux-yocto-tiny_5.10.bb8
-rw-r--r--meta/recipes-kernel/linux/linux-yocto-tiny_5.4.bb8
-rw-r--r--meta/recipes-kernel/linux/linux-yocto_5.10.bb26
-rw-r--r--meta/recipes-kernel/linux/linux-yocto_5.4.bb22
-rw-r--r--meta/recipes-kernel/lttng/lttng-modules_2.12.8.bb (renamed from meta/recipes-kernel/lttng/lttng-modules_2.12.6.bb)2
-rw-r--r--meta/recipes-kernel/wireless-regdb/wireless-regdb_2022.02.18.bb (renamed from meta/recipes-kernel/wireless-regdb/wireless-regdb_2021.08.28.bb)2
-rw-r--r--meta/recipes-multimedia/flac/flac/CVE-2021-0561.patch41
-rw-r--r--meta/recipes-multimedia/flac/flac_1.3.3.bb1
-rw-r--r--meta/recipes-multimedia/gstreamer/gst-devtools_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gst-devtools_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gst-examples_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gst-examples_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-rtpjitterbuffer-Fix-parsing-of-the-mediaclk-direct-f.patch33
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.4.bb)3
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-Remove-unused-valgrind-detection.patch14
-rw-r--r--meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.6.bb (renamed from meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.4.bb)2
-rw-r--r--meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2021-4156.patch32
-rw-r--r--meta/recipes-multimedia/libsndfile/libsndfile1_1.0.28.bb1
-rw-r--r--meta/recipes-multimedia/speex/speex/CVE-2020-23903.patch30
-rw-r--r--meta/recipes-multimedia/speex/speex_1.2.0.bb4
-rw-r--r--meta/recipes-sato/webkit/webkitgtk/CVE-2021-42762.patch468
-rw-r--r--meta/recipes-sato/webkit/webkitgtk/reproducibility.patch22
-rw-r--r--meta/recipes-sato/webkit/webkitgtk_2.30.6.bb (renamed from meta/recipes-sato/webkit/webkitgtk_2.30.5.bb)4
-rw-r--r--meta/recipes-support/curl/curl/CVE-2021-22945.patch35
-rw-r--r--meta/recipes-support/curl/curl/CVE-2021-22946.patch333
-rw-r--r--meta/recipes-support/curl/curl/CVE-2021-22947.patch357
-rw-r--r--meta/recipes-support/curl/curl_7.75.0.bb8
-rw-r--r--meta/recipes-support/gmp/gmp/cve-2021-43618.patch27
-rw-r--r--meta/recipes-support/gmp/gmp_6.2.1.bb1
-rw-r--r--meta/recipes-support/libgcrypt/libgcrypt_1.9.4.bb (renamed from meta/recipes-support/libgcrypt/libgcrypt_1.9.3.bb)2
-rw-r--r--meta/recipes-support/libpcre/libpcre2_10.36.bb4
-rw-r--r--meta/recipes-support/libpcre/libpcre_8.44.bb2
-rw-r--r--meta/recipes-support/libusb/libusb1_1.0.24.bb6
-rw-r--r--meta/recipes-support/vim/files/0001-src-Makefile-improve-reproducibility.patch13
-rw-r--r--meta/recipes-support/vim/files/CVE-2021-3778.patch34
-rw-r--r--meta/recipes-support/vim/files/CVE-2021-3872.patch57
-rw-r--r--meta/recipes-support/vim/files/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9.patch207
-rw-r--r--meta/recipes-support/vim/files/disable_acl_header_check.patch15
-rw-r--r--meta/recipes-support/vim/files/no-path-adjust.patch8
-rw-r--r--meta/recipes-support/vim/files/racefix.patch6
-rw-r--r--meta/recipes-support/vim/files/vim-add-knob-whether-elf.h-are-checked.patch13
-rw-r--r--meta/recipes-support/vim/vim.inc15
-rwxr-xr-xscripts/buildhistory-diff5
-rw-r--r--scripts/lib/checklayer/cases/common.py2
-rw-r--r--scripts/lib/devtool/deploy.py2
-rw-r--r--scripts/lib/recipetool/create.py19
-rw-r--r--scripts/lib/recipetool/create_buildsys.py3
-rw-r--r--scripts/lib/scriptutils.py7
-rw-r--r--scripts/lib/wic/engine.py6
-rw-r--r--scripts/lib/wic/misc.py4
-rw-r--r--scripts/lib/wic/pluginbase.py8
-rw-r--r--scripts/lib/wic/plugins/imager/direct.py2
-rwxr-xr-xscripts/runqemu3
-rwxr-xr-xscripts/runqemu-ifdown1
-rwxr-xr-xscripts/wic7
-rwxr-xr-xscripts/yocto-check-layer13
232 files changed, 19068 insertions, 3218 deletions
diff --git a/README.OE-Core b/README.OE-Core
index 521916cd4f..2f2127fb03 100644
--- a/README.OE-Core
+++ b/README.OE-Core
@@ -6,24 +6,24 @@ of OpenEmbedded. It is distro-less (can build a functional image with
6DISTRO = "nodistro") and contains only emulated machine support. 6DISTRO = "nodistro") and contains only emulated machine support.
7 7
8For information about OpenEmbedded, see the OpenEmbedded website: 8For information about OpenEmbedded, see the OpenEmbedded website:
9 http://www.openembedded.org/ 9 https://www.openembedded.org/
10 10
11The Yocto Project has extensive documentation about OE including a reference manual 11The Yocto Project has extensive documentation about OE including a reference manual
12which can be found at: 12which can be found at:
13 http://yoctoproject.org/documentation 13 https://docs.yoctoproject.org/
14 14
15 15
16Contributing 16Contributing
17------------ 17------------
18 18
19Please refer to 19Please refer to
20http://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded 20https://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded
21for guidelines on how to submit patches. 21for guidelines on how to submit patches.
22 22
23Mailing list: 23Mailing list:
24 24
25 http://lists.openembedded.org/mailman/listinfo/openembedded-core 25 https://lists.openembedded.org/g/openembedded-core
26 26
27Source code: 27Source code:
28 28
29 http://git.openembedded.org/openembedded-core/ 29 https://git.openembedded.org/openembedded-core/
diff --git a/bitbake/lib/bb/process.py b/bitbake/lib/bb/process.py
index d5a1775fce..af5d804a1d 100644
--- a/bitbake/lib/bb/process.py
+++ b/bitbake/lib/bb/process.py
@@ -60,7 +60,7 @@ class Popen(subprocess.Popen):
60 "close_fds": True, 60 "close_fds": True,
61 "preexec_fn": subprocess_setup, 61 "preexec_fn": subprocess_setup,
62 "stdout": subprocess.PIPE, 62 "stdout": subprocess.PIPE,
63 "stderr": subprocess.STDOUT, 63 "stderr": subprocess.PIPE,
64 "stdin": subprocess.PIPE, 64 "stdin": subprocess.PIPE,
65 "shell": False, 65 "shell": False,
66 } 66 }
diff --git a/bitbake/lib/bb/server/process.py b/bitbake/lib/bb/server/process.py
index fcdce19717..b11c903e08 100644
--- a/bitbake/lib/bb/server/process.py
+++ b/bitbake/lib/bb/server/process.py
@@ -26,6 +26,7 @@ import errno
26import re 26import re
27import datetime 27import datetime
28import pickle 28import pickle
29import gc
29import bb.server.xmlrpcserver 30import bb.server.xmlrpcserver
30from bb import daemonize 31from bb import daemonize
31from multiprocessing import queues 32from multiprocessing import queues
@@ -737,8 +738,10 @@ class ConnectionWriter(object):
737 738
738 def send(self, obj): 739 def send(self, obj):
739 obj = multiprocessing.reduction.ForkingPickler.dumps(obj) 740 obj = multiprocessing.reduction.ForkingPickler.dumps(obj)
741 gc.disable()
740 with self.wlock: 742 with self.wlock:
741 self.writer.send_bytes(obj) 743 self.writer.send_bytes(obj)
744 gc.enable()
742 745
743 def fileno(self): 746 def fileno(self):
744 return self.writer.fileno() 747 return self.writer.fileno()
diff --git a/bitbake/lib/bb/server/xmlrpcserver.py b/bitbake/lib/bb/server/xmlrpcserver.py
index 2fa71be667..01f55538ae 100644
--- a/bitbake/lib/bb/server/xmlrpcserver.py
+++ b/bitbake/lib/bb/server/xmlrpcserver.py
@@ -11,6 +11,7 @@ import hashlib
11import time 11import time
12import inspect 12import inspect
13from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler 13from xmlrpc.server import SimpleXMLRPCServer, SimpleXMLRPCRequestHandler
14import bb.server.xmlrpcclient
14 15
15import bb 16import bb
16 17
diff --git a/bitbake/lib/bb/tests/fetch.py b/bitbake/lib/bb/tests/fetch.py
index 86eccf7de2..19ea725ac6 100644
--- a/bitbake/lib/bb/tests/fetch.py
+++ b/bitbake/lib/bb/tests/fetch.py
@@ -1059,7 +1059,7 @@ class FetcherNetworkTest(FetcherTest):
1059 """ Prevent regression on deeply nested submodules not being checked out properly, even though they were fetched. """ 1059 """ Prevent regression on deeply nested submodules not being checked out properly, even though they were fetched. """
1060 1060
1061 # This repository also has submodules where the module (name), path and url do not align 1061 # This repository also has submodules where the module (name), path and url do not align
1062 url = "gitsm://github.com/azure/iotedge.git;protocol=https;rev=d76e0316c6f324345d77c48a83ce836d09392699" 1062 url = "gitsm://github.com/azure/iotedge.git;protocol=https;rev=d76e0316c6f324345d77c48a83ce836d09392699;branch=main"
1063 fetcher = bb.fetch.Fetch([url], self.d) 1063 fetcher = bb.fetch.Fetch([url], self.d)
1064 fetcher.download() 1064 fetcher.download()
1065 # Previous cwd has been deleted 1065 # Previous cwd has been deleted
@@ -1358,9 +1358,6 @@ class FetchCheckStatusTest(FetcherTest):
1358 "http://downloads.yoctoproject.org/releases/opkg/opkg-0.1.7.tar.gz", 1358 "http://downloads.yoctoproject.org/releases/opkg/opkg-0.1.7.tar.gz",
1359 "http://downloads.yoctoproject.org/releases/opkg/opkg-0.3.0.tar.gz", 1359 "http://downloads.yoctoproject.org/releases/opkg/opkg-0.3.0.tar.gz",
1360 "ftp://sourceware.org/pub/libffi/libffi-1.20.tar.gz", 1360 "ftp://sourceware.org/pub/libffi/libffi-1.20.tar.gz",
1361 "http://ftp.gnu.org/gnu/autoconf/autoconf-2.60.tar.gz",
1362 "https://ftp.gnu.org/gnu/chess/gnuchess-5.08.tar.gz",
1363 "https://ftp.gnu.org/gnu/gmp/gmp-4.0.tar.gz",
1364 # GitHub releases are hosted on Amazon S3, which doesn't support HEAD 1361 # GitHub releases are hosted on Amazon S3, which doesn't support HEAD
1365 "https://github.com/kergoth/tslib/releases/download/1.1/tslib-1.1.tar.xz" 1362 "https://github.com/kergoth/tslib/releases/download/1.1/tslib-1.1.tar.xz"
1366 ] 1363 ]
diff --git a/bitbake/lib/bb/utils.py b/bitbake/lib/bb/utils.py
index b282d09abf..2a150fe9c7 100644
--- a/bitbake/lib/bb/utils.py
+++ b/bitbake/lib/bb/utils.py
@@ -16,7 +16,8 @@ import bb.msg
16import multiprocessing 16import multiprocessing
17import fcntl 17import fcntl
18import importlib 18import importlib
19from importlib import machinery 19import importlib.machinery
20import importlib.util
20import itertools 21import itertools
21import subprocess 22import subprocess
22import glob 23import glob
@@ -451,6 +452,10 @@ def lockfile(name, shared=False, retry=True, block=False):
451 consider the possibility of sending a signal to the process to break 452 consider the possibility of sending a signal to the process to break
452 out - at which point you want block=True rather than retry=True. 453 out - at which point you want block=True rather than retry=True.
453 """ 454 """
455 if len(name) > 255:
456 root, ext = os.path.splitext(name)
457 name = root[:255 - len(ext)] + ext
458
454 dirname = os.path.dirname(name) 459 dirname = os.path.dirname(name)
455 mkdirhier(dirname) 460 mkdirhier(dirname)
456 461
@@ -487,7 +492,7 @@ def lockfile(name, shared=False, retry=True, block=False):
487 return lf 492 return lf
488 lf.close() 493 lf.close()
489 except OSError as e: 494 except OSError as e:
490 if e.errno == errno.EACCES: 495 if e.errno == errno.EACCES or e.errno == errno.ENAMETOOLONG:
491 logger.error("Unable to acquire lock '%s', %s", 496 logger.error("Unable to acquire lock '%s', %s",
492 e.strerror, name) 497 e.strerror, name)
493 sys.exit(1) 498 sys.exit(1)
@@ -1616,7 +1621,9 @@ def load_plugins(logger, plugins, pluginpath):
1616 logger.debug('Loading plugin %s' % name) 1621 logger.debug('Loading plugin %s' % name)
1617 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] ) 1622 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] )
1618 if spec: 1623 if spec:
1619 return spec.loader.load_module() 1624 mod = importlib.util.module_from_spec(spec)
1625 spec.loader.exec_module(mod)
1626 return mod
1620 1627
1621 logger.debug('Loading plugins from %s...' % pluginpath) 1628 logger.debug('Loading plugins from %s...' % pluginpath)
1622 1629
diff --git a/bitbake/lib/toaster/orm/fixtures/oe-core.xml b/bitbake/lib/toaster/orm/fixtures/oe-core.xml
index 026d94869a..bb58c6f1bb 100644
--- a/bitbake/lib/toaster/orm/fixtures/oe-core.xml
+++ b/bitbake/lib/toaster/orm/fixtures/oe-core.xml
@@ -23,9 +23,9 @@
23 <field type="CharField" name="branch">master</field> 23 <field type="CharField" name="branch">master</field>
24 </object> 24 </object>
25 <object model="orm.bitbakeversion" pk="4"> 25 <object model="orm.bitbakeversion" pk="4">
26 <field type="CharField" name="name">gatesgarth</field> 26 <field type="CharField" name="name">hardknott</field>
27 <field type="CharField" name="giturl">git://git.openembedded.org/bitbake</field> 27 <field type="CharField" name="giturl">git://git.openembedded.org/bitbake</field>
28 <field type="CharField" name="branch">1.48</field> 28 <field type="CharField" name="branch">1.50</field>
29 </object> 29 </object>
30 30
31 <!-- Releases available --> 31 <!-- Releases available -->
@@ -51,11 +51,11 @@
51 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/\"&gt;OpenEmbedded master&lt;/a&gt; branch.</field> 51 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/\"&gt;OpenEmbedded master&lt;/a&gt; branch.</field>
52 </object> 52 </object>
53 <object model="orm.release" pk="4"> 53 <object model="orm.release" pk="4">
54 <field type="CharField" name="name">gatesgarth</field> 54 <field type="CharField" name="name">hardknott</field>
55 <field type="CharField" name="description">Openembedded Gatesgarth</field> 55 <field type="CharField" name="description">Openembedded Hardknott</field>
56 <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field> 56 <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field>
57 <field type="CharField" name="branch_name">gatesgarth</field> 57 <field type="CharField" name="branch_name">hardknott</field>
58 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/?h=gatesgarth\"&gt;OpenEmbedded Gatesgarth&lt;/a&gt; branch.</field> 58 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href=\"http://cgit.openembedded.org/openembedded-core/log/?h=hardknott\"&gt;OpenEmbedded Hardknott&lt;/a&gt; branch.</field>
59 </object> 59 </object>
60 60
61 <!-- Default layers for each release --> 61 <!-- Default layers for each release -->
diff --git a/bitbake/lib/toaster/orm/fixtures/poky.xml b/bitbake/lib/toaster/orm/fixtures/poky.xml
index a468a54c49..483d9d8fb4 100644
--- a/bitbake/lib/toaster/orm/fixtures/poky.xml
+++ b/bitbake/lib/toaster/orm/fixtures/poky.xml
@@ -26,9 +26,9 @@
26 <field type="CharField" name="dirpath">bitbake</field> 26 <field type="CharField" name="dirpath">bitbake</field>
27 </object> 27 </object>
28 <object model="orm.bitbakeversion" pk="4"> 28 <object model="orm.bitbakeversion" pk="4">
29 <field type="CharField" name="name">gatesgarth</field> 29 <field type="CharField" name="name">hardknott</field>
30 <field type="CharField" name="giturl">git://git.yoctoproject.org/poky</field> 30 <field type="CharField" name="giturl">git://git.yoctoproject.org/poky</field>
31 <field type="CharField" name="branch">gatesgarth</field> 31 <field type="CharField" name="branch">hardknott</field>
32 <field type="CharField" name="dirpath">bitbake</field> 32 <field type="CharField" name="dirpath">bitbake</field>
33 </object> 33 </object>
34 34
@@ -56,11 +56,11 @@
56 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/"&gt;Yocto Project Master branch&lt;/a&gt;.</field> 56 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/"&gt;Yocto Project Master branch&lt;/a&gt;.</field>
57 </object> 57 </object>
58 <object model="orm.release" pk="4"> 58 <object model="orm.release" pk="4">
59 <field type="CharField" name="name">gatesgarth</field> 59 <field type="CharField" name="name">hardknott</field>
60 <field type="CharField" name="description">Yocto Project 3.2 "Gatesgarth"</field> 60 <field type="CharField" name="description">Yocto Project 3.2 "Hardknott"</field>
61 <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field> 61 <field rel="ManyToOneRel" to="orm.bitbakeversion" name="bitbake_version">4</field>
62 <field type="CharField" name="branch_name">gatesgarth</field> 62 <field type="CharField" name="branch_name">hardknott</field>
63 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?h=gatesgarth"&gt;Yocto Project Gatesgarth branch&lt;/a&gt;.</field> 63 <field type="TextField" name="helptext">Toaster will run your builds using the tip of the &lt;a href="http://git.yoctoproject.org/cgit/cgit.cgi/poky/log/?h=hardknott"&gt;Yocto Project Hardknott branch&lt;/a&gt;.</field>
64 </object> 64 </object>
65 65
66 <!-- Default project layers for each release --> 66 <!-- Default project layers for each release -->
@@ -152,7 +152,7 @@
152 <field rel="ManyToOneRel" to="orm.layer" name="layer">1</field> 152 <field rel="ManyToOneRel" to="orm.layer" name="layer">1</field>
153 <field type="IntegerField" name="layer_source">0</field> 153 <field type="IntegerField" name="layer_source">0</field>
154 <field rel="ManyToOneRel" to="orm.release" name="release">4</field> 154 <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
155 <field type="CharField" name="branch">gatesgarth</field> 155 <field type="CharField" name="branch">hardknott</field>
156 <field type="CharField" name="dirpath">meta</field> 156 <field type="CharField" name="dirpath">meta</field>
157 </object> 157 </object>
158 158
@@ -190,7 +190,7 @@
190 <field rel="ManyToOneRel" to="orm.layer" name="layer">2</field> 190 <field rel="ManyToOneRel" to="orm.layer" name="layer">2</field>
191 <field type="IntegerField" name="layer_source">0</field> 191 <field type="IntegerField" name="layer_source">0</field>
192 <field rel="ManyToOneRel" to="orm.release" name="release">4</field> 192 <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
193 <field type="CharField" name="branch">gatesgarth</field> 193 <field type="CharField" name="branch">hardknott</field>
194 <field type="CharField" name="dirpath">meta-poky</field> 194 <field type="CharField" name="dirpath">meta-poky</field>
195 </object> 195 </object>
196 196
@@ -228,7 +228,7 @@
228 <field rel="ManyToOneRel" to="orm.layer" name="layer">3</field> 228 <field rel="ManyToOneRel" to="orm.layer" name="layer">3</field>
229 <field type="IntegerField" name="layer_source">0</field> 229 <field type="IntegerField" name="layer_source">0</field>
230 <field rel="ManyToOneRel" to="orm.release" name="release">4</field> 230 <field rel="ManyToOneRel" to="orm.release" name="release">4</field>
231 <field type="CharField" name="branch">gatesgarth</field> 231 <field type="CharField" name="branch">hardknott</field>
232 <field type="CharField" name="dirpath">meta-yocto-bsp</field> 232 <field type="CharField" name="dirpath">meta-yocto-bsp</field>
233 </object> 233 </object>
234</django-objects> 234</django-objects>
diff --git a/bitbake/lib/toaster/orm/fixtures/settings.xml b/bitbake/lib/toaster/orm/fixtures/settings.xml
index 78c0fdca7f..ab3ea021f5 100644
--- a/bitbake/lib/toaster/orm/fixtures/settings.xml
+++ b/bitbake/lib/toaster/orm/fixtures/settings.xml
@@ -19,7 +19,7 @@
19 <field type="CharField" name="value">${TOPDIR}/../sstate-cache</field> 19 <field type="CharField" name="value">${TOPDIR}/../sstate-cache</field>
20 </object> 20 </object>
21 <object model="orm.toastersetting" pk="6"> 21 <object model="orm.toastersetting" pk="6">
22 <field type="CharField" name="name">DEFCONF_IMAGE_INSTALL_append</field> 22 <field type="CharField" name="name">DEFCONF_IMAGE_INSTALL:append</field>
23 <field type="CharField" name="value"></field> 23 <field type="CharField" name="value"></field>
24 </object> 24 </object>
25 <object model="orm.toastersetting" pk="7"> 25 <object model="orm.toastersetting" pk="7">
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 7f7e922ade..f73951e213 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -1717,7 +1717,7 @@ class CustomImageRecipe(Recipe):
1717 1717
1718 def generate_recipe_file_contents(self): 1718 def generate_recipe_file_contents(self):
1719 """Generate the contents for the recipe file.""" 1719 """Generate the contents for the recipe file."""
1720 # If we have no excluded packages we only need to _append 1720 # If we have no excluded packages we only need to :append
1721 if self.excludes_set.count() == 0: 1721 if self.excludes_set.count() == 0:
1722 packages_conf = "IMAGE_INSTALL_append = \" " 1722 packages_conf = "IMAGE_INSTALL_append = \" "
1723 1723
diff --git a/bitbake/lib/toaster/toastergui/templates/projectconf.html b/bitbake/lib/toaster/toastergui/templates/projectconf.html
index bd49f1f585..c74adf0a7e 100644
--- a/bitbake/lib/toaster/toastergui/templates/projectconf.html
+++ b/bitbake/lib/toaster/toastergui/templates/projectconf.html
@@ -73,7 +73,7 @@
73 73
74 {% if image_install_append_defined %} 74 {% if image_install_append_defined %}
75 <dt> 75 <dt>
76 <span class="js-config-var-name js-config-var-managed-name">IMAGE_INSTALL_append</span> 76 <span class="js-config-var-name js-config-var-managed-name">IMAGE_INSTALL:append</span>
77 <span class="glyphicon glyphicon-question-sign get-help" title="Specifies additional packages to install into an image. If your build creates more than one image, the packages will be installed in all of them"></span> 77 <span class="glyphicon glyphicon-question-sign get-help" title="Specifies additional packages to install into an image. If your build creates more than one image, the packages will be installed in all of them"></span>
78 </dt> 78 </dt>
79 <dd class="variable-list"> 79 <dd class="variable-list">
@@ -83,7 +83,7 @@
83 <form id="change-image_install-form" class="form-inline" style="display:none;"> 83 <form id="change-image_install-form" class="form-inline" style="display:none;">
84 <div class="row"> 84 <div class="row">
85 <div class="col-md-4"> 85 <div class="col-md-4">
86 <span class="help-block">To set IMAGE_INSTALL_append to more than one package, type the package names separated by a space.</span> 86 <span class="help-block">To set IMAGE_INSTALL:append to more than one package, type the package names separated by a space.</span>
87 </div> 87 </div>
88 </div> 88 </div>
89 <div class="form-group"> 89 <div class="form-group">
@@ -771,10 +771,10 @@ $(document).ready(function() {
771 771
772 {% if image_install_append_defined %} 772 {% if image_install_append_defined %}
773 773
774 // init IMAGE_INSTALL_append trash icon 774 // init IMAGE_INSTALL:append trash icon
775 setDeleteTooltip($('#delete-image_install-icon')); 775 setDeleteTooltip($('#delete-image_install-icon'));
776 776
777 // change IMAGE_INSTALL_append variable 777 // change IMAGE_INSTALL:append variable
778 $('#change-image_install-icon').click(function() { 778 $('#change-image_install-icon').click(function() {
779 // preset the edit value 779 // preset the edit value
780 var current_val = $("span#image_install").text().trim(); 780 var current_val = $("span#image_install").text().trim();
@@ -814,7 +814,7 @@ $(document).ready(function() {
814 $('#apply-change-image_install').click(function(){ 814 $('#apply-change-image_install').click(function(){
815 // insure these non-empty values have single space prefix 815 // insure these non-empty values have single space prefix
816 var value = " " + $('#new-image_install').val().trim(); 816 var value = " " + $('#new-image_install').val().trim();
817 postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL_append:'+value}); 817 postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL:append:'+value});
818 $('#image_install').text(value); 818 $('#image_install').text(value);
819 $('#image_install').removeClass('text-muted'); 819 $('#image_install').removeClass('text-muted');
820 $("#change-image_install-form").slideUp(function () { 820 $("#change-image_install-form").slideUp(function () {
@@ -826,10 +826,10 @@ $(document).ready(function() {
826 }); 826 });
827 }); 827 });
828 828
829 // delete IMAGE_INSTALL_append variable value 829 // delete IMAGE_INSTALL:append variable value
830 $('#delete-image_install-icon').click(function(){ 830 $('#delete-image_install-icon').click(function(){
831 $(this).tooltip('hide'); 831 $(this).tooltip('hide');
832 postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL_append:'+''}); 832 postEditAjaxRequest({"configvarChange" : 'IMAGE_INSTALL:append:'+''});
833 $('#image_install').parent().fadeOut(1000, function(){ 833 $('#image_install').parent().fadeOut(1000, function(){
834 $('#image_install').addClass('text-muted'); 834 $('#image_install').addClass('text-muted');
835 $('#image_install').text('Not set'); 835 $('#image_install').text('Not set');
@@ -1011,7 +1011,7 @@ $(document).ready(function() {
1011 $(".save").attr("disabled","disabled"); 1011 $(".save").attr("disabled","disabled");
1012 1012
1013 // Reload page if admin-removed core managed value is manually added back in 1013 // Reload page if admin-removed core managed value is manually added back in
1014 if (0 <= " DISTRO DL_DIR IMAGE_FSTYPES IMAGE_INSTALL_append PACKAGE_CLASSES SSTATE_DIR ".indexOf( " "+variable+" " )) { 1014 if (0 <= " DISTRO DL_DIR IMAGE_FSTYPES IMAGE_INSTALL:append PACKAGE_CLASSES SSTATE_DIR ".indexOf( " "+variable+" " )) {
1015 // delayed reload to avoid race condition with postEditAjaxRequest 1015 // delayed reload to avoid race condition with postEditAjaxRequest
1016 do_reload=true; 1016 do_reload=true;
1017 } 1017 }
diff --git a/documentation/bsp-guide/bsp.rst b/documentation/bsp-guide/bsp.rst
index 89f1564422..daa7ba4bb2 100644
--- a/documentation/bsp-guide/bsp.rst
+++ b/documentation/bsp-guide/bsp.rst
@@ -166,8 +166,8 @@ section.
166#. *Determine the BSP Layer You Want:* The Yocto Project supports many 166#. *Determine the BSP Layer You Want:* The Yocto Project supports many
167 BSPs, which are maintained in their own layers or in layers designed 167 BSPs, which are maintained in their own layers or in layers designed
168 to contain several BSPs. To get an idea of machine support through 168 to contain several BSPs. To get an idea of machine support through
169 BSP layers, you can look at the `index of 169 BSP layers, you can look at the :yocto_dl:`index of machines
170 machines <&YOCTO_RELEASE_DL_URL;/machines>`__ for the release. 170 </releases/yocto/&DISTRO_REL_TAG;/machines>`
171 171
172#. *Optionally Clone the meta-intel BSP Layer:* If your hardware is 172#. *Optionally Clone the meta-intel BSP Layer:* If your hardware is
173 based on current Intel CPUs and devices, you can leverage this BSP 173 based on current Intel CPUs and devices, you can leverage this BSP
@@ -879,7 +879,7 @@ Yocto Project:
879 your BSP layer as listed in the ``recipes.txt`` file, which is found 879 your BSP layer as listed in the ``recipes.txt`` file, which is found
880 in ``poky/meta`` directory of the :term:`Source Directory` 880 in ``poky/meta`` directory of the :term:`Source Directory`
881 or in the OpenEmbedded-Core Layer (``openembedded-core``) at 881 or in the OpenEmbedded-Core Layer (``openembedded-core``) at
882 https://git.openembedded.org/openembedded-core/tree/meta. 882 :oe_git:`/openembedded-core/tree/meta`.
883 883
884 You should place recipes (``*.bb`` files) and recipe modifications 884 You should place recipes (``*.bb`` files) and recipe modifications
885 (``*.bbappend`` files) into ``recipes-*`` subdirectories by 885 (``*.bbappend`` files) into ``recipes-*`` subdirectories by
diff --git a/documentation/conf.py b/documentation/conf.py
index 28af37d7b1..d2478ae00b 100644
--- a/documentation/conf.py
+++ b/documentation/conf.py
@@ -15,8 +15,27 @@
15import os 15import os
16import sys 16import sys
17import datetime 17import datetime
18try:
19 import yaml
20except ImportError:
21 sys.stderr.write("The Yocto Project Sphinx documentation requires PyYAML.\
22 \nPlease make sure to install pyyaml python package.\n")
23 sys.exit(1)
18 24
19current_version = "3.3.4" 25# current_version = "dev"
26# bitbake_version = "" # Leave empty for development branch
27# Obtain versions from poky.yaml instead
28with open("poky.yaml") as data:
29 buff = data.read()
30 subst_vars = yaml.safe_load(buff)
31 if "DOCCONF_VERSION" not in subst_vars:
32 sys.stderr.write("Please set DOCCONF_VERSION in poky.yaml")
33 sys.exit(1)
34 current_version = subst_vars["DOCCONF_VERSION"]
35 if "BITBAKE_SERIES" not in subst_vars:
36 sys.stderr.write("Please set BITBAKE_SERIES in poky.yaml")
37 sys.exit(1)
38 bitbake_version = subst_vars["BITBAKE_SERIES"]
20 39
21# String used in sidebar 40# String used in sidebar
22version = 'Version: ' + current_version 41version = 'Version: ' + current_version
@@ -89,7 +108,7 @@ extlinks = {
89 108
90# Intersphinx config to use cross reference with Bitbake user manual 109# Intersphinx config to use cross reference with Bitbake user manual
91intersphinx_mapping = { 110intersphinx_mapping = {
92 'bitbake': ('https://docs.yoctoproject.org/bitbake/', None) 111 'bitbake': ('https://docs.yoctoproject.org/bitbake/' + bitbake_version, None)
93} 112}
94 113
95# -- Options for HTML output ------------------------------------------------- 114# -- Options for HTML output -------------------------------------------------
diff --git a/documentation/overview-manual/yp-intro.rst b/documentation/overview-manual/yp-intro.rst
index fca02e4cec..8e0c6a8cb1 100644
--- a/documentation/overview-manual/yp-intro.rst
+++ b/documentation/overview-manual/yp-intro.rst
@@ -221,7 +221,7 @@ your Metadata, the easier it is to cope with future changes.
221 possible. 221 possible.
222 222
223 - Familiarize yourself with the `Yocto Project curated layer 223 - Familiarize yourself with the `Yocto Project curated layer
224 index <https://www.yoctoproject.org/software-overview/layers/>`__ 224 index :yocto_home:`/software-overview/layers/`
225 or the :oe_layerindex:`OpenEmbedded layer index <>`. 225 or the :oe_layerindex:`OpenEmbedded layer index <>`.
226 The latter contains more layers but they are less universally 226 The latter contains more layers but they are less universally
227 validated. 227 validated.
diff --git a/documentation/poky.yaml b/documentation/poky.yaml
index 30eb453796..d57b4d7101 100644
--- a/documentation/poky.yaml
+++ b/documentation/poky.yaml
@@ -1,12 +1,14 @@
1DISTRO : "3.3.4" 1DISTRO : "3.3.6"
2DISTRO_NAME_NO_CAP : "hardknott" 2DISTRO_NAME_NO_CAP : "hardknott"
3DISTRO_NAME : "Hardknott" 3DISTRO_NAME : "Hardknott"
4DISTRO_NAME_NO_CAP_MINUS_ONE : "gatesgarth" 4DISTRO_NAME_NO_CAP_MINUS_ONE : "gatesgarth"
5DISTRO_NAME_NO_CAP_LTS : "gatesgarth" 5DISTRO_NAME_NO_CAP_LTS : "gatesgarth"
6YOCTO_DOC_VERSION : "3.3.4" 6YOCTO_DOC_VERSION : "3.3.6"
7YOCTO_DOC_VERSION_MINUS_ONE : "3.2.4" 7YOCTO_DOC_VERSION_MINUS_ONE : "3.2.4"
8DISTRO_REL_TAG : "yocto-3.3.4" 8DISTRO_REL_TAG : "yocto-3.3.6"
9POKYVERSION : "25.0.4" 9DOCCONF_VERSION : "3.3.6"
10BITBAKE_SERIES : "1.50"
11POKYVERSION : "25.0.6"
10YOCTO_POKY : "poky-&DISTRO_NAME_NO_CAP;-&POKYVERSION;" 12YOCTO_POKY : "poky-&DISTRO_NAME_NO_CAP;-&POKYVERSION;"
11YOCTO_DL_URL : "https://downloads.yoctoproject.org" 13YOCTO_DL_URL : "https://downloads.yoctoproject.org"
12YOCTO_AB_URL : "https://autobuilder.yoctoproject.org" 14YOCTO_AB_URL : "https://autobuilder.yoctoproject.org"
diff --git a/documentation/ref-manual/system-requirements.rst b/documentation/ref-manual/system-requirements.rst
index 80378cedb7..38a3974a30 100644
--- a/documentation/ref-manual/system-requirements.rst
+++ b/documentation/ref-manual/system-requirements.rst
@@ -339,7 +339,7 @@ If you would prefer not to use the ``install-buildtools`` script, you can instea
339download and run a pre-built buildtools installer yourself with the following 339download and run a pre-built buildtools installer yourself with the following
340steps: 340steps:
341 341
3421. Locate and download the ``*.sh`` at &YOCTO_RELEASE_DL_URL;/buildtools/ 3421. Locate and download the ``*.sh`` at :yocto_dl:`/releases/yocto/&DISTRO_REL_TAG;/buildtools/`
343 343
3442. Execute the installation script. Here is an example for the 3442. Execute the installation script. Here is an example for the
345 traditional installer: 345 traditional installer:
diff --git a/documentation/ref-manual/tasks.rst b/documentation/ref-manual/tasks.rst
index 9fe1c296aa..ca19908bc9 100644
--- a/documentation/ref-manual/tasks.rst
+++ b/documentation/ref-manual/tasks.rst
@@ -331,22 +331,19 @@ file as a patch file:
331 file://file;apply=yes \ 331 file://file;apply=yes \
332 " 332 "
333 333
334Conversely, if you have a directory full of patch files and you want to 334Conversely, if you have a file whose file type is ``.patch`` or ``.diff``
335exclude some so that the ``do_patch`` task does not apply them during 335and you want to exclude it so that the ``do_patch`` task does not apply
336the patch phase, you can use the "apply=no" parameter with the 336it during the patch phase, you can use the "apply=no" parameter with the
337``SRC_URI`` statement: 337:term:`SRC_URI` statement::
338::
339 338
340 SRC_URI = " \ 339 SRC_URI = " \
341 git://path_to_repo/some_package \ 340 git://path_to_repo/some_package \
342 file://path_to_lots_of_patch_files \ 341 file://file1.patch \
343 file://path_to_lots_of_patch_files/patch_file5;apply=no \ 342 file://file2.patch;apply=no \
344 " 343 "
345 344
346In the 345In the previous example ``file1.patch`` would be applied as a patch by default
347previous example, assuming all the files in the directory holding the 346while ``file2.patch`` would not be applied.
348patch files end with either ``.patch`` or ``.diff``, every file would be
349applied as a patch by default except for the ``patch_file5`` patch.
350 347
351You can find out more about the patching process in the 348You can find out more about the patching process in the
352":ref:`overview-manual/concepts:patching`" section in 349":ref:`overview-manual/concepts:patching`" section in
diff --git a/documentation/releases.rst b/documentation/releases.rst
index e19dfde6c8..233448c68a 100644
--- a/documentation/releases.rst
+++ b/documentation/releases.rst
@@ -5,6 +5,15 @@
5========================= 5=========================
6 6
7******************************* 7*******************************
83.4 'honister' Release Series
9*******************************
10
11- :yocto_docs:`3.4 Documentation </3.4>`
12- :yocto_docs:`3.4.1 Documentation </3.4.1>`
13- :yocto_docs:`3.4.2 Documentation </3.4.2>`
14- :yocto_docs:`3.4.3 Documentation </3.4.3>`
15
16*******************************
83.3 'hardknott' Release Series 173.3 'hardknott' Release Series
9******************************* 18*******************************
10 19
@@ -13,17 +22,8 @@
13- :yocto_docs:`3.3.2 Documentation </3.3.2>` 22- :yocto_docs:`3.3.2 Documentation </3.3.2>`
14- :yocto_docs:`3.3.3 Documentation </3.3.3>` 23- :yocto_docs:`3.3.3 Documentation </3.3.3>`
15- :yocto_docs:`3.3.4 Documentation </3.3.4>` 24- :yocto_docs:`3.3.4 Documentation </3.3.4>`
16 25- :yocto_docs:`3.3.5 Documentation </3.3.5>`
17 26- :yocto_docs:`3.3.6 Documentation </3.3.6>`
18*******************************
193.2 'gatesgarth' Release Series
20*******************************
21
22- :yocto_docs:`3.2 Documentation </3.2>`
23- :yocto_docs:`3.2.1 Documentation </3.2.1>`
24- :yocto_docs:`3.2.2 Documentation </3.2.2>`
25- :yocto_docs:`3.2.3 Documentation </3.2.3>`
26- :yocto_docs:`3.2.4 Documentation </3.2.4>`
27 27
28**************************** 28****************************
293.1 'dunfell' Release Series 293.1 'dunfell' Release Series
@@ -41,11 +41,25 @@
41- :yocto_docs:`3.1.9 Documentation </3.1.9>` 41- :yocto_docs:`3.1.9 Documentation </3.1.9>`
42- :yocto_docs:`3.1.10 Documentation </3.1.10>` 42- :yocto_docs:`3.1.10 Documentation </3.1.10>`
43- :yocto_docs:`3.1.11 Documentation </3.1.11>` 43- :yocto_docs:`3.1.11 Documentation </3.1.11>`
44- :yocto_docs:`3.1.12 Documentation </3.1.12>`
45- :yocto_docs:`3.1.13 Documentation </3.1.13>`
46- :yocto_docs:`3.1.14 Documentation </3.1.14>`
47- :yocto_docs:`3.1.15 Documentation </3.1.15>`
44 48
45========================== 49==========================
46 Previous Release Manuals 50 Previous Release Manuals
47========================== 51==========================
48 52
53*******************************
543.2 'gatesgarth' Release Series
55*******************************
56
57- :yocto_docs:`3.2 Documentation </3.2>`
58- :yocto_docs:`3.2.1 Documentation </3.2.1>`
59- :yocto_docs:`3.2.2 Documentation </3.2.2>`
60- :yocto_docs:`3.2.3 Documentation </3.2.3>`
61- :yocto_docs:`3.2.4 Documentation </3.2.4>`
62
49************************* 63*************************
503.0 'zeus' Release Series 643.0 'zeus' Release Series
51************************* 65*************************
diff --git a/documentation/sphinx-static/switchers.js b/documentation/sphinx-static/switchers.js
index 7a4edc9e77..056a8926ba 100644
--- a/documentation/sphinx-static/switchers.js
+++ b/documentation/sphinx-static/switchers.js
@@ -2,9 +2,11 @@
2 'use strict'; 2 'use strict';
3 3
4 var all_versions = { 4 var all_versions = {
5 'dev': 'dev (3.3)', 5 'dev': 'dev (3.5)',
6 '3.2.3': '3.2.3', 6 '3.4.1': '3.4.1',
7 '3.1.6': '3.1.6', 7 '3.3.4': '3.3.4',
8 '3.2.4': '3.2.4',
9 '3.1.12': '3.1.12',
8 '3.0.4': '3.0.4', 10 '3.0.4': '3.0.4',
9 '2.7.4': '2.7.4', 11 '2.7.4': '2.7.4',
10 }; 12 };
diff --git a/meta-poky/conf/distro/include/gcsections.inc b/meta-poky/conf/distro/include/gcsections.inc
index 7157373aa8..75d8613794 100644
--- a/meta-poky/conf/distro/include/gcsections.inc
+++ b/meta-poky/conf/distro/include/gcsections.inc
@@ -16,6 +16,8 @@ LDFLAGS_SECTION_REMOVAL_pn-grub = ""
16# SDK packages with build problems using sections 16# SDK packages with build problems using sections
17CFLAGS_SECTION_REMOVAL_pn-nativesdk-glibc = "" 17CFLAGS_SECTION_REMOVAL_pn-nativesdk-glibc = ""
18LDFLAGS_SECTION_REMOVAL_pn-nativesdk-glibc = "" 18LDFLAGS_SECTION_REMOVAL_pn-nativesdk-glibc = ""
19CFLAGS_SECTION_REMOVAL_pn-nativesdk-cairo = ""
20LDFLAGS_SECTION_REMOVAL_pn-nativesdk-cairo = ""
19CFLAGS_SECTION_REMOVAL_pn-nativesdk-mingw-w64-runtime = "" 21CFLAGS_SECTION_REMOVAL_pn-nativesdk-mingw-w64-runtime = ""
20LDFLAGS_SECTION_REMOVAL_pn-nativesdk-mingw-w64-runtime = "" 22LDFLAGS_SECTION_REMOVAL_pn-nativesdk-mingw-w64-runtime = ""
21CFLAGS_SECTION_REMOVAL_pn-nativesdk-perl = "" 23CFLAGS_SECTION_REMOVAL_pn-nativesdk-perl = ""
diff --git a/meta-poky/conf/distro/poky.conf b/meta-poky/conf/distro/poky.conf
index 966e66d149..0b78d65f18 100644
--- a/meta-poky/conf/distro/poky.conf
+++ b/meta-poky/conf/distro/poky.conf
@@ -1,6 +1,6 @@
1DISTRO = "poky" 1DISTRO = "poky"
2DISTRO_NAME = "Poky (Yocto Project Reference Distro)" 2DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
3DISTRO_VERSION = "3.3.4" 3DISTRO_VERSION = "3.3.6"
4DISTRO_CODENAME = "hardknott" 4DISTRO_CODENAME = "hardknott"
5SDK_VENDOR = "-pokysdk" 5SDK_VENDOR = "-pokysdk"
6SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}" 6SDK_VERSION = "${@d.getVar('DISTRO_VERSION').replace('snapshot-${METADATA_REVISION}', 'snapshot')}"
@@ -49,11 +49,13 @@ SANITY_TESTED_DISTROS ?= " \
49 fedora-31 \n \ 49 fedora-31 \n \
50 fedora-32 \n \ 50 fedora-32 \n \
51 fedora-33 \n \ 51 fedora-33 \n \
52 fedora-34 \n \
52 centos-7 \n \ 53 centos-7 \n \
53 centos-8 \n \ 54 centos-8 \n \
54 debian-8 \n \ 55 debian-8 \n \
55 debian-9 \n \ 56 debian-9 \n \
56 debian-10 \n \ 57 debian-10 \n \
58 debian-11 \n \
57 opensuseleap-15.1 \n \ 59 opensuseleap-15.1 \n \
58 opensuseleap-15.2 \n \ 60 opensuseleap-15.2 \n \
59 " 61 "
diff --git a/meta-selftest/recipes-test/gitrepotest/gitrepotest.bb b/meta-selftest/recipes-test/gitrepotest/gitrepotest.bb
new file mode 100644
index 0000000000..f1b6c55833
--- /dev/null
+++ b/meta-selftest/recipes-test/gitrepotest/gitrepotest.bb
@@ -0,0 +1,16 @@
1SUMMARY = "Test recipe for git repo initialization"
2HOMEPAGE = "https://git.yoctoproject.org/git/matchbox-panel-2"
3LICENSE = "GPL-2.0-or-later"
4LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f"
5
6INHIBIT_DEFAULT_DEPS = "1"
7
8PATCHTOOL="git"
9
10SRC_URI = "git://git.yoctoproject.org/git/matchbox-panel-2;branch=master;protocol=https \
11 file://0001-testpatch.patch \
12 "
13
14SRCREV = "f82ca3f42510fb3ef10f598b393eb373a2c34ca7"
15
16S = "${WORKDIR}/git"
diff --git a/meta-selftest/recipes-test/gitrepotest/gitrepotest/0001-testpatch.patch b/meta-selftest/recipes-test/gitrepotest/gitrepotest/0001-testpatch.patch
new file mode 100644
index 0000000000..bccda17ee9
--- /dev/null
+++ b/meta-selftest/recipes-test/gitrepotest/gitrepotest/0001-testpatch.patch
@@ -0,0 +1,9 @@
1diff --git a/Makefile.am b/Makefile.am
2index 432a9b4..bbf7c74 100644
3--- a/Makefile.am
4+++ b/Makefile.am
5@@ -1,3 +1,4 @@
6+## This is useless comment to test if patch works
7 ACLOCAL_AMFLAGS = -I m4
8
9 SUBDIRS = matchbox-panel applets data po
diff --git a/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.10.bbappend b/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.10.bbappend
index 347a411341..b9bb9a087c 100644
--- a/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.10.bbappend
+++ b/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.10.bbappend
@@ -7,8 +7,8 @@ KMACHINE_genericx86 ?= "common-pc"
7KMACHINE_genericx86-64 ?= "common-pc-64" 7KMACHINE_genericx86-64 ?= "common-pc-64"
8KMACHINE_beaglebone-yocto ?= "beaglebone" 8KMACHINE_beaglebone-yocto ?= "beaglebone"
9 9
10SRCREV_machine_genericx86 ?= "164ed895bc1e94722e80fe6496b176f6bb815cd4" 10SRCREV_machine_genericx86 ?= "84f6a75f64961e59d61bf3d70ab17e8bb430386b"
11SRCREV_machine_genericx86-64 ?= "164ed895bc1e94722e80fe6496b176f6bb815cd4" 11SRCREV_machine_genericx86-64 ?= "84f6a75f64961e59d61bf3d70ab17e8bb430386b"
12SRCREV_machine_edgerouter ?= "4ab94e777d8b41ee1ee4c279259e9733bc8049b1" 12SRCREV_machine_edgerouter ?= "4ab94e777d8b41ee1ee4c279259e9733bc8049b1"
13SRCREV_machine_beaglebone-yocto ?= "941cc9c3849f96f7eaf109b1e35e05ba366aca56" 13SRCREV_machine_beaglebone-yocto ?= "941cc9c3849f96f7eaf109b1e35e05ba366aca56"
14 14
@@ -17,7 +17,7 @@ COMPATIBLE_MACHINE_genericx86-64 = "genericx86-64"
17COMPATIBLE_MACHINE_edgerouter = "edgerouter" 17COMPATIBLE_MACHINE_edgerouter = "edgerouter"
18COMPATIBLE_MACHINE_beaglebone-yocto = "beaglebone-yocto" 18COMPATIBLE_MACHINE_beaglebone-yocto = "beaglebone-yocto"
19 19
20LINUX_VERSION_genericx86 = "5.10.63" 20LINUX_VERSION_genericx86 = "5.10.99"
21LINUX_VERSION_genericx86-64 = "5.10.63" 21LINUX_VERSION_genericx86-64 = "5.10.99"
22LINUX_VERSION_edgerouter = "5.10.63" 22LINUX_VERSION_edgerouter = "5.10.63"
23LINUX_VERSION_beaglebone-yocto = "5.10.63" 23LINUX_VERSION_beaglebone-yocto = "5.10.63"
diff --git a/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.4.bbappend b/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.4.bbappend
index 35147d2da8..b2824cbb1d 100644
--- a/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.4.bbappend
+++ b/meta-yocto-bsp/recipes-kernel/linux/linux-yocto_5.4.bbappend
@@ -7,8 +7,8 @@ KMACHINE_genericx86 ?= "common-pc"
7KMACHINE_genericx86-64 ?= "common-pc-64" 7KMACHINE_genericx86-64 ?= "common-pc-64"
8KMACHINE_beaglebone-yocto ?= "beaglebone" 8KMACHINE_beaglebone-yocto ?= "beaglebone"
9 9
10SRCREV_machine_genericx86 ?= "31db2b47ac7d8508080fbb7344399b501216de66" 10SRCREV_machine_genericx86 ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
11SRCREV_machine_genericx86-64 ?= "31db2b47ac7d8508080fbb7344399b501216de66" 11SRCREV_machine_genericx86-64 ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
12SRCREV_machine_edgerouter ?= "706efec4c1e270ec5dda92275898cd465dfdc7dd" 12SRCREV_machine_edgerouter ?= "706efec4c1e270ec5dda92275898cd465dfdc7dd"
13SRCREV_machine_beaglebone-yocto ?= "706efec4c1e270ec5dda92275898cd465dfdc7dd" 13SRCREV_machine_beaglebone-yocto ?= "706efec4c1e270ec5dda92275898cd465dfdc7dd"
14 14
@@ -17,7 +17,7 @@ COMPATIBLE_MACHINE_genericx86-64 = "genericx86-64"
17COMPATIBLE_MACHINE_edgerouter = "edgerouter" 17COMPATIBLE_MACHINE_edgerouter = "edgerouter"
18COMPATIBLE_MACHINE_beaglebone-yocto = "beaglebone-yocto" 18COMPATIBLE_MACHINE_beaglebone-yocto = "beaglebone-yocto"
19 19
20LINUX_VERSION_genericx86 = "5.4.94" 20LINUX_VERSION_genericx86 = "5.4.178"
21LINUX_VERSION_genericx86-64 = "5.4.94" 21LINUX_VERSION_genericx86-64 = "5.4.178"
22LINUX_VERSION_edgerouter = "5.4.58" 22LINUX_VERSION_edgerouter = "5.4.58"
23LINUX_VERSION_beaglebone-yocto = "5.4.58" 23LINUX_VERSION_beaglebone-yocto = "5.4.58"
diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass
index 49af61c9c5..b2cf9aa28a 100644
--- a/meta/classes/buildhistory.bbclass
+++ b/meta/classes/buildhistory.bbclass
@@ -960,23 +960,19 @@ def write_latest_srcrev(d, pkghistdir):
960 value = value.replace('"', '').strip() 960 value = value.replace('"', '').strip()
961 old_tag_srcrevs[key] = value 961 old_tag_srcrevs[key] = value
962 with open(srcrevfile, 'w') as f: 962 with open(srcrevfile, 'w') as f:
963 orig_srcrev = d.getVar('SRCREV', False) or 'INVALID' 963 for name, srcrev in sorted(srcrevs.items()):
964 if orig_srcrev != 'INVALID': 964 suffix = "_" + name
965 f.write('# SRCREV = "%s"\n' % orig_srcrev) 965 if name == "default":
966 if len(srcrevs) > 1: 966 suffix = ""
967 for name, srcrev in sorted(srcrevs.items()): 967 orig_srcrev = d.getVar('SRCREV%s' % suffix, False)
968 orig_srcrev = d.getVar('SRCREV_%s' % name, False) 968 if orig_srcrev:
969 if orig_srcrev: 969 f.write('# SRCREV%s = "%s"\n' % (suffix, orig_srcrev))
970 f.write('# SRCREV_%s = "%s"\n' % (name, orig_srcrev)) 970 f.write('SRCREV%s = "%s"\n' % (suffix, srcrev))
971 f.write('SRCREV_%s = "%s"\n' % (name, srcrev)) 971 for name, srcrev in sorted(tag_srcrevs.items()):
972 else: 972 f.write('# tag_%s = "%s"\n' % (name, srcrev))
973 f.write('SRCREV = "%s"\n' % next(iter(srcrevs.values()))) 973 if name in old_tag_srcrevs and old_tag_srcrevs[name] != srcrev:
974 if len(tag_srcrevs) > 0: 974 pkg = d.getVar('PN')
975 for name, srcrev in sorted(tag_srcrevs.items()): 975 bb.warn("Revision for tag %s in package %s was changed since last build (from %s to %s)" % (name, pkg, old_tag_srcrevs[name], srcrev))
976 f.write('# tag_%s = "%s"\n' % (name, srcrev))
977 if name in old_tag_srcrevs and old_tag_srcrevs[name] != srcrev:
978 pkg = d.getVar('PN')
979 bb.warn("Revision for tag %s in package %s was changed since last build (from %s to %s)" % (name, pkg, old_tag_srcrevs[name], srcrev))
980 976
981 else: 977 else:
982 if os.path.exists(srcrevfile): 978 if os.path.exists(srcrevfile):
diff --git a/meta/classes/cve-check.bbclass b/meta/classes/cve-check.bbclass
index 4fa1a64f85..a95e810605 100644
--- a/meta/classes/cve-check.bbclass
+++ b/meta/classes/cve-check.bbclass
@@ -110,6 +110,7 @@ python do_cve_check () {
110} 110}
111 111
112addtask cve_check before do_build after do_fetch 112addtask cve_check before do_build after do_fetch
113do_cve_check[lockfiles] += "${CVE_CHECK_DB_FILE_LOCK}"
113do_cve_check[depends] = "cve-update-db-native:do_fetch" 114do_cve_check[depends] = "cve-update-db-native:do_fetch"
114do_cve_check[nostamp] = "1" 115do_cve_check[nostamp] = "1"
115 116
@@ -142,6 +143,7 @@ python cve_check_write_rootfs_manifest () {
142 manifest_name = d.getVar("CVE_CHECK_MANIFEST") 143 manifest_name = d.getVar("CVE_CHECK_MANIFEST")
143 cve_tmp_file = d.getVar("CVE_CHECK_TMP_FILE") 144 cve_tmp_file = d.getVar("CVE_CHECK_TMP_FILE")
144 145
146 bb.utils.mkdirhier(os.path.dirname(manifest_name))
145 shutil.copyfile(cve_tmp_file, manifest_name) 147 shutil.copyfile(cve_tmp_file, manifest_name)
146 148
147 if manifest_name and os.path.exists(manifest_name): 149 if manifest_name and os.path.exists(manifest_name):
diff --git a/meta/classes/populate_sdk_base.bbclass b/meta/classes/populate_sdk_base.bbclass
index 2d33611ddd..76757a3a9d 100644
--- a/meta/classes/populate_sdk_base.bbclass
+++ b/meta/classes/populate_sdk_base.bbclass
@@ -90,6 +90,8 @@ SDK_HOST_MANIFEST = "${SDKDEPLOYDIR}/${TOOLCHAIN_OUTPUTNAME}.host.manifest"
90SDK_EXT_TARGET_MANIFEST = "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.target.manifest" 90SDK_EXT_TARGET_MANIFEST = "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.target.manifest"
91SDK_EXT_HOST_MANIFEST = "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.host.manifest" 91SDK_EXT_HOST_MANIFEST = "${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.host.manifest"
92 92
93SDK_PRUNE_SYSROOT_DIRS ?= "/dev"
94
93python write_target_sdk_manifest () { 95python write_target_sdk_manifest () {
94 from oe.sdk import sdk_list_installed_packages 96 from oe.sdk import sdk_list_installed_packages
95 from oe.utils import format_pkg_list 97 from oe.utils import format_pkg_list
@@ -101,6 +103,12 @@ python write_target_sdk_manifest () {
101 output.write(format_pkg_list(pkgs, 'ver')) 103 output.write(format_pkg_list(pkgs, 'ver'))
102} 104}
103 105
106sdk_prune_dirs () {
107 for d in ${SDK_PRUNE_SYSROOT_DIRS}; do
108 rm -rf ${SDK_OUTPUT}${SDKTARGETSYSROOT}$d
109 done
110}
111
104python write_sdk_test_data() { 112python write_sdk_test_data() {
105 from oe.data import export2json 113 from oe.data import export2json
106 testdata = "%s/%s.testdata.json" % (d.getVar('SDKDEPLOYDIR'), d.getVar('TOOLCHAIN_OUTPUTNAME')) 114 testdata = "%s/%s.testdata.json" % (d.getVar('SDKDEPLOYDIR'), d.getVar('TOOLCHAIN_OUTPUTNAME'))
@@ -120,8 +128,9 @@ python write_host_sdk_manifest () {
120} 128}
121 129
122POPULATE_SDK_POST_TARGET_COMMAND_append = " write_sdk_test_data ; " 130POPULATE_SDK_POST_TARGET_COMMAND_append = " write_sdk_test_data ; "
123POPULATE_SDK_POST_TARGET_COMMAND_append_task-populate-sdk = " write_target_sdk_manifest ; " 131POPULATE_SDK_POST_TARGET_COMMAND_append_task-populate-sdk = " write_target_sdk_manifest; sdk_prune_dirs; "
124POPULATE_SDK_POST_HOST_COMMAND_append_task-populate-sdk = " write_host_sdk_manifest; " 132POPULATE_SDK_POST_HOST_COMMAND_append_task-populate-sdk = " write_host_sdk_manifest; "
133
125SDK_PACKAGING_COMMAND = "${@'${SDK_PACKAGING_FUNC};' if '${SDK_PACKAGING_FUNC}' else ''}" 134SDK_PACKAGING_COMMAND = "${@'${SDK_PACKAGING_FUNC};' if '${SDK_PACKAGING_FUNC}' else ''}"
126SDK_POSTPROCESS_COMMAND = " create_sdk_files; check_sdk_sysroots; archive_sdk; ${SDK_PACKAGING_COMMAND} " 135SDK_POSTPROCESS_COMMAND = " create_sdk_files; check_sdk_sysroots; archive_sdk; ${SDK_PACKAGING_COMMAND} "
127 136
diff --git a/meta/classes/rootfs-postcommands.bbclass b/meta/classes/rootfs-postcommands.bbclass
index e66ed5938b..87b5751e24 100644
--- a/meta/classes/rootfs-postcommands.bbclass
+++ b/meta/classes/rootfs-postcommands.bbclass
@@ -60,7 +60,7 @@ python () {
60} 60}
61 61
62systemd_create_users () { 62systemd_create_users () {
63 for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd.conf ${IMAGE_ROOTFS}/usr/lib/sysusers.d/systemd-remote.conf; do 63 for conffile in ${IMAGE_ROOTFS}/usr/lib/sysusers.d/*.conf; do
64 [ -e $conffile ] || continue 64 [ -e $conffile ] || continue
65 grep -v "^#" $conffile | sed -e '/^$/d' | while read type name id comment; do 65 grep -v "^#" $conffile | sed -e '/^$/d' | while read type name id comment; do
66 if [ "$type" = "u" ]; then 66 if [ "$type" = "u" ]; then
diff --git a/meta/classes/sanity.bbclass b/meta/classes/sanity.bbclass
index a2ac4eeb80..c8a42dc8bf 100644
--- a/meta/classes/sanity.bbclass
+++ b/meta/classes/sanity.bbclass
@@ -395,7 +395,7 @@ def check_connectivity(d):
395 msg += " Please ensure your host's network is configured correctly.\n" 395 msg += " Please ensure your host's network is configured correctly.\n"
396 msg += " If your ISP or network is blocking the above URL,\n" 396 msg += " If your ISP or network is blocking the above URL,\n"
397 msg += " try with another domain name, for example by setting:\n" 397 msg += " try with another domain name, for example by setting:\n"
398 msg += " CONNECTIVITY_CHECK_URIS = \"https://www.yoctoproject.org/\"" 398 msg += " CONNECTIVITY_CHECK_URIS = \"https://www.example.com/\""
399 msg += " You could also set BB_NO_NETWORK = \"1\" to disable network\n" 399 msg += " You could also set BB_NO_NETWORK = \"1\" to disable network\n"
400 msg += " access if all required sources are on local disk.\n" 400 msg += " access if all required sources are on local disk.\n"
401 retval = msg 401 retval = msg
diff --git a/meta/classes/sstate.bbclass b/meta/classes/sstate.bbclass
index da29225983..de6e7fa960 100644
--- a/meta/classes/sstate.bbclass
+++ b/meta/classes/sstate.bbclass
@@ -827,14 +827,18 @@ sstate_create_package () {
827 fi 827 fi
828 chmod 0664 $TFILE 828 chmod 0664 $TFILE
829 # Skip if it was already created by some other process 829 # Skip if it was already created by some other process
830 if [ ! -e ${SSTATE_PKG} ]; then 830 if [ -h ${SSTATE_PKG} ] && [ ! -e ${SSTATE_PKG} ]; then
831 # There is a symbolic link, but it links to nothing.
832 # Forcefully replace it with the new file.
833 ln -f $TFILE ${SSTATE_PKG} || true
834 elif [ ! -e ${SSTATE_PKG} ]; then
831 # Move into place using ln to attempt an atomic op. 835 # Move into place using ln to attempt an atomic op.
832 # Abort if it already exists 836 # Abort if it already exists
833 ln $TFILE ${SSTATE_PKG} && rm $TFILE 837 ln $TFILE ${SSTATE_PKG} || true
834 else 838 else
835 rm $TFILE 839 touch ${SSTATE_PKG} 2>/dev/null || true
836 fi 840 fi
837 touch ${SSTATE_PKG} 2>/dev/null || true 841 rm $TFILE
838} 842}
839 843
840python sstate_sign_package () { 844python sstate_sign_package () {
@@ -864,7 +868,7 @@ python sstate_report_unihash() {
864sstate_unpack_package () { 868sstate_unpack_package () {
865 tar -xvzf ${SSTATE_PKG} 869 tar -xvzf ${SSTATE_PKG}
866 # update .siginfo atime on local/NFS mirror if it is a symbolic link 870 # update .siginfo atime on local/NFS mirror if it is a symbolic link
867 [ ! -h ${SSTATE_PKG}.siginfo ] || touch -a ${SSTATE_PKG}.siginfo 2>/dev/null || true 871 [ ! -h ${SSTATE_PKG}.siginfo ] || [ ! -e ${SSTATE_PKG}.siginfo ] || touch -a ${SSTATE_PKG}.siginfo 2>/dev/null || true
868 # update each symbolic link instead of any referenced file 872 # update each symbolic link instead of any referenced file
869 touch --no-dereference ${SSTATE_PKG} 2>/dev/null || true 873 touch --no-dereference ${SSTATE_PKG} 2>/dev/null || true
870 [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig 2>/dev/null || true 874 [ ! -e ${SSTATE_PKG}.sig ] || touch --no-dereference ${SSTATE_PKG}.sig 2>/dev/null || true
@@ -946,7 +950,7 @@ def sstate_checkhashes(sq_data, d, siginfo=False, currentcount=0, summary=True,
946 950
947 localdata2 = bb.data.createCopy(localdata) 951 localdata2 = bb.data.createCopy(localdata)
948 srcuri = "file://" + sstatefile 952 srcuri = "file://" + sstatefile
949 localdata.setVar('SRC_URI', srcuri) 953 localdata2.setVar('SRC_URI', srcuri)
950 bb.debug(2, "SState: Attempting to fetch %s" % srcuri) 954 bb.debug(2, "SState: Attempting to fetch %s" % srcuri)
951 955
952 try: 956 try:
diff --git a/meta/classes/toaster.bbclass b/meta/classes/toaster.bbclass
index 9518ddf7a4..f365c09142 100644
--- a/meta/classes/toaster.bbclass
+++ b/meta/classes/toaster.bbclass
@@ -101,12 +101,12 @@ def _toaster_load_pkgdatafile(dirpath, filepath):
101 for line in fin: 101 for line in fin:
102 try: 102 try:
103 kn, kv = line.strip().split(": ", 1) 103 kn, kv = line.strip().split(": ", 1)
104 m = re.match(r"^PKG_([^A-Z:]*)", kn) 104 m = re.match(r"^PKG:([^A-Z:]*)", kn)
105 if m: 105 if m:
106 pkgdata['OPKGN'] = m.group(1) 106 pkgdata['OPKGN'] = m.group(1)
107 kn = "_".join([x for x in kn.split("_") if x.isupper()]) 107 kn = kn.split(":")[0]
108 pkgdata[kn] = kv.strip() 108 pkgdata[kn] = kv
109 if kn == 'FILES_INFO': 109 if kn.startswith('FILES_INFO'):
110 pkgdata[kn] = json.loads(kv) 110 pkgdata[kn] = json.loads(kv)
111 111
112 except ValueError: 112 except ValueError:
diff --git a/meta/classes/uboot-sign.bbclass b/meta/classes/uboot-sign.bbclass
index ba48f24b10..fca9de2934 100644
--- a/meta/classes/uboot-sign.bbclass
+++ b/meta/classes/uboot-sign.bbclass
@@ -131,6 +131,20 @@ concat_dtb_helper() {
131 elif [ -e "${DEPLOYDIR}/${UBOOT_NODTB_IMAGE}" -a -e "$deployed_uboot_dtb_binary" ]; then 131 elif [ -e "${DEPLOYDIR}/${UBOOT_NODTB_IMAGE}" -a -e "$deployed_uboot_dtb_binary" ]; then
132 cd ${DEPLOYDIR} 132 cd ${DEPLOYDIR}
133 cat ${UBOOT_NODTB_IMAGE} $deployed_uboot_dtb_binary | tee ${B}/${CONFIG_B_PATH}/${UBOOT_BINARY} > ${UBOOT_IMAGE} 133 cat ${UBOOT_NODTB_IMAGE} $deployed_uboot_dtb_binary | tee ${B}/${CONFIG_B_PATH}/${UBOOT_BINARY} > ${UBOOT_IMAGE}
134
135 if [ -n "${UBOOT_CONFIG}" ]
136 then
137 for config in ${UBOOT_MACHINE}; do
138 i=$(expr $i + 1);
139 for type in ${UBOOT_CONFIG}; do
140 j=$(expr $j + 1);
141 if [ $j -eq $i ]
142 then
143 cp ${UBOOT_IMAGE} ${B}/${CONFIG_B_PATH}/u-boot-$type.${UBOOT_SUFFIX}
144 fi
145 done
146 done
147 fi
134 else 148 else
135 bbwarn "Failure while adding public key to u-boot binary. Verified boot won't be available." 149 bbwarn "Failure while adding public key to u-boot binary. Verified boot won't be available."
136 fi 150 fi
@@ -205,7 +219,7 @@ install_helper() {
205 fi 219 fi
206} 220}
207 221
208# Install SPL dtb and u-boot nodtb to datadir, 222# Install SPL dtb and u-boot nodtb to datadir,
209install_spl_helper() { 223install_spl_helper() {
210 if [ -f "${SPL_DIR}/${SPL_DTB_BINARY}" ]; then 224 if [ -f "${SPL_DIR}/${SPL_DTB_BINARY}" ]; then
211 install -Dm 0644 ${SPL_DIR}/${SPL_DTB_BINARY} ${D}${datadir}/${SPL_DTB_IMAGE} 225 install -Dm 0644 ${SPL_DIR}/${SPL_DTB_BINARY} ${D}${datadir}/${SPL_DTB_IMAGE}
diff --git a/meta/classes/uninative.bbclass b/meta/classes/uninative.bbclass
index 3c7ccd66f4..4412d7c567 100644
--- a/meta/classes/uninative.bbclass
+++ b/meta/classes/uninative.bbclass
@@ -2,7 +2,7 @@ UNINATIVE_LOADER ?= "${UNINATIVE_STAGING_DIR}-uninative/${BUILD_ARCH}-linux/lib/
2UNINATIVE_STAGING_DIR ?= "${STAGING_DIR}" 2UNINATIVE_STAGING_DIR ?= "${STAGING_DIR}"
3 3
4UNINATIVE_URL ?= "unset" 4UNINATIVE_URL ?= "unset"
5UNINATIVE_TARBALL ?= "${BUILD_ARCH}-nativesdk-libc.tar.xz" 5UNINATIVE_TARBALL ?= "${BUILD_ARCH}-nativesdk-libc-${UNINATIVE_VERSION}.tar.xz"
6# Example checksums 6# Example checksums
7#UNINATIVE_CHECKSUM[aarch64] = "dead" 7#UNINATIVE_CHECKSUM[aarch64] = "dead"
8#UNINATIVE_CHECKSUM[i686] = "dead" 8#UNINATIVE_CHECKSUM[i686] = "dead"
diff --git a/meta/conf/distro/include/cve-extra-exclusions.inc b/meta/conf/distro/include/cve-extra-exclusions.inc
index 561386b706..0b8bec312b 100644
--- a/meta/conf/distro/include/cve-extra-exclusions.inc
+++ b/meta/conf/distro/include/cve-extra-exclusions.inc
@@ -43,3 +43,12 @@ CVE_CHECK_WHITELIST += "CVE-2010-4756"
43# CVE applies to a netapp product as well as flagging a general issue. We don't ship anything 43# CVE applies to a netapp product as well as flagging a general issue. We don't ship anything
44# exposing this interface in an exploitable way 44# exposing this interface in an exploitable way
45CVE_CHECK_WHITELIST += "CVE-2020-29509 CVE-2020-29511" 45CVE_CHECK_WHITELIST += "CVE-2020-29509 CVE-2020-29511"
46
47# db
48# Since Oracle relicensed bdb, the open source community is slowly but surely replacing bdb with
49# supported and open source friendly alternatives. As a result these CVEs are unlikely to ever be fixed.
50CVE_CHECK_WHITELIST += "CVE-2015-2583 CVE-2015-2624 CVE-2015-2626 CVE-2015-2640 CVE-2015-2654 \
51CVE-2015-2656 CVE-2015-4754 CVE-2015-4764 CVE-2015-4774 CVE-2015-4775 CVE-2015-4776 CVE-2015-4777 \
52CVE-2015-4778 CVE-2015-4779 CVE-2015-4780 CVE-2015-4781 CVE-2015-4782 CVE-2015-4783 CVE-2015-4784 \
53CVE-2015-4785 CVE-2015-4786 CVE-2015-4787 CVE-2015-4788 CVE-2015-4789 CVE-2015-4790 CVE-2016-0682 \
54CVE-2016-0689 CVE-2016-0692 CVE-2016-0694 CVE-2016-3418 CVE-2020-2981"
diff --git a/meta/conf/distro/include/default-distrovars.inc b/meta/conf/distro/include/default-distrovars.inc
index 0240589c81..038acc1504 100644
--- a/meta/conf/distro/include/default-distrovars.inc
+++ b/meta/conf/distro/include/default-distrovars.inc
@@ -48,4 +48,4 @@ KERNEL_IMAGETYPES ??= "${KERNEL_IMAGETYPE}"
48# fetch from the network (and warn you if not). To disable the test set 48# fetch from the network (and warn you if not). To disable the test set
49# the variable to be empty. 49# the variable to be empty.
50# Git example url: git://git.yoctoproject.org/yocto-firewall-test;protocol=git;rev=master;branch=master 50# Git example url: git://git.yoctoproject.org/yocto-firewall-test;protocol=git;rev=master;branch=master
51CONNECTIVITY_CHECK_URIS ?= "https://www.example.com/" 51CONNECTIVITY_CHECK_URIS ?= "https://yoctoproject.org/connectivity.html"
diff --git a/meta/conf/distro/include/maintainers.inc b/meta/conf/distro/include/maintainers.inc
index 5d453a6fcd..5064ee6b79 100644
--- a/meta/conf/distro/include/maintainers.inc
+++ b/meta/conf/distro/include/maintainers.inc
@@ -191,7 +191,7 @@ RECIPE_MAINTAINER_pn-gcc-cross-canadian-${TRANSLATED_TARGET_ARCH} = "Khem Raj <r
191RECIPE_MAINTAINER_pn-gcc-crosssdk-${SDK_SYS} = "Khem Raj <raj.khem@gmail.com>" 191RECIPE_MAINTAINER_pn-gcc-crosssdk-${SDK_SYS} = "Khem Raj <raj.khem@gmail.com>"
192RECIPE_MAINTAINER_pn-gcc-runtime = "Khem Raj <raj.khem@gmail.com>" 192RECIPE_MAINTAINER_pn-gcc-runtime = "Khem Raj <raj.khem@gmail.com>"
193RECIPE_MAINTAINER_pn-gcc-sanitizers = "Khem Raj <raj.khem@gmail.com>" 193RECIPE_MAINTAINER_pn-gcc-sanitizers = "Khem Raj <raj.khem@gmail.com>"
194RECIPE_MAINTAINER_pn-gcc-source-10.2.0 = "Khem Raj <raj.khem@gmail.com>" 194RECIPE_MAINTAINER_pn-gcc-source-10.3.0 = "Khem Raj <raj.khem@gmail.com>"
195RECIPE_MAINTAINER_pn-gconf = "Ross Burton <ross.burton@arm.com>" 195RECIPE_MAINTAINER_pn-gconf = "Ross Burton <ross.burton@arm.com>"
196RECIPE_MAINTAINER_pn-gcr = "Alexander Kanavin <alex.kanavin@gmail.com>" 196RECIPE_MAINTAINER_pn-gcr = "Alexander Kanavin <alex.kanavin@gmail.com>"
197RECIPE_MAINTAINER_pn-gdb = "Khem Raj <raj.khem@gmail.com>" 197RECIPE_MAINTAINER_pn-gdb = "Khem Raj <raj.khem@gmail.com>"
diff --git a/meta/conf/distro/include/yocto-uninative.inc b/meta/conf/distro/include/yocto-uninative.inc
index 3165fc93b8..bfe05ce1eb 100644
--- a/meta/conf/distro/include/yocto-uninative.inc
+++ b/meta/conf/distro/include/yocto-uninative.inc
@@ -6,9 +6,10 @@
6# to the distro running on the build machine. 6# to the distro running on the build machine.
7# 7#
8 8
9UNINATIVE_MAXGLIBCVERSION = "2.34" 9UNINATIVE_MAXGLIBCVERSION = "2.35"
10UNINATIVE_VERSION = "3.5"
10 11
11UNINATIVE_URL ?= "http://downloads.yoctoproject.org/releases/uninative/3.4/" 12UNINATIVE_URL ?= "http://downloads.yoctoproject.org/releases/uninative/${UNINATIVE_VERSION}/"
12UNINATIVE_CHECKSUM[aarch64] ?= "3013cdda8f0dc6639ce1c80f33eabce66f06b890bd5b58739a6d7a92a0bb7100" 13UNINATIVE_CHECKSUM[aarch64] ?= "6de0771bd21e0fcb5e80388e5b561a8023b24083bcbf46e056a089982aff75d7"
13UNINATIVE_CHECKSUM[i686] ?= "abed500de584aad63ec237546db20cdd0c69d8870a6f8e94ac31721ace64b376" 14UNINATIVE_CHECKSUM[i686] ?= "8c8745becbfa1c341bae839c7eab56ddf17ce36c303bcd73d3b2f2f788b631c2"
14UNINATIVE_CHECKSUM[x86_64] ?= "126f4f7f6f21084ee140dac3eb4c536b963837826b7c38599db0b512c3377ba2" 15UNINATIVE_CHECKSUM[x86_64] ?= "e8047a5748e6f266165da141eb6d08b23674f30e477b0e5505b6403d50fbc4b2"
diff --git a/meta/conf/machine/include/arm/arch-armv8-5a.inc b/meta/conf/machine/include/arm/arch-armv8-5a.inc
new file mode 100644
index 0000000000..44c3b5bd22
--- /dev/null
+++ b/meta/conf/machine/include/arm/arch-armv8-5a.inc
@@ -0,0 +1,19 @@
1DEFAULTTUNE ?= "armv8-5a"
2
3TUNEVALID[armv8-5a] = "Enable instructions for ARMv8.5-a"
4TUNE_CCARGS .= "${@bb.utils.contains('TUNE_FEATURES', 'armv8-5a', ' -march=armv8.5-a', '', d)}"
5# TUNE crypto will be handled by arch-armv8a.inc below
6MACHINEOVERRIDES =. "${@bb.utils.contains('TUNE_FEATURES', 'armv8-5a', 'armv8-5a:', '', d)}"
7
8require conf/machine/include/arm/arch-armv8a.inc
9
10# Little Endian base configs
11AVAILTUNES += "armv8-5a armv8-5a-crypto"
12ARMPKGARCH_tune-armv8-5a ?= "armv8-5a"
13ARMPKGARCH_tune-armv8-5a-crypto ?= "armv8-5a"
14TUNE_FEATURES_tune-armv8-5a = "aarch64 armv8-5a"
15TUNE_FEATURES_tune-armv8-5a-crypto = "${TUNE_FEATURES_tune-armv8-5a} crypto"
16PACKAGE_EXTRA_ARCHS_tune-armv8-5a = "${PACKAGE_EXTRA_ARCHS_tune-armv8a} armv8-5a"
17PACKAGE_EXTRA_ARCHS_tune-armv8-5a-crypto = "${PACKAGE_EXTRA_ARCHS_tune-armv8-5a} armv8-5a-crypto"
18BASE_LIB_tune-armv8-5a = "lib64"
19BASE_LIB_tune-armv8-5a-crypto = "lib64"
diff --git a/meta/conf/machine/include/arm/armv9a/tune-neoversen2.inc b/meta/conf/machine/include/arm/armv9a/tune-neoversen2.inc
new file mode 100644
index 0000000000..dedabcf46e
--- /dev/null
+++ b/meta/conf/machine/include/arm/armv9a/tune-neoversen2.inc
@@ -0,0 +1,22 @@
1#
2# Tune Settings for Neoverse-N2
3#
4DEFAULTTUNE ?= "neoversen2"
5
6TUNEVALID[neoversen2] = "Enable Neoverse-N2 specific processor optimizations"
7TUNE_CCARGS .= "${@bb.utils.contains('TUNE_FEATURES', 'neoversen2', ' -mcpu=neoverse-n2', '', d)}"
8
9# Even though the Neoverse N2 core implemnts the Arm v9.0-A architecture,
10# but the support of it in GCC is based on the Arm v8.5-A architecture.
11require conf/machine/include/arm/arch-armv8-5a.inc
12
13# Little Endian base configs
14AVAILTUNES += "neoversen2 neoversen2-crypto"
15ARMPKGARCH_tune-neoversen2 = "neoversen2"
16ARMPKGARCH_tune-neoversen2-crypto = "neoversen2-crypto"
17TUNE_FEATURES_tune-neoversen2 = "${TUNE_FEATURES_tune-armv8-5a} neoversen2"
18TUNE_FEATURES_tune-neoversen2-crypto = "${TUNE_FEATURES_tune-neoversen2} crypto"
19PACKAGE_EXTRA_ARCHS_tune-neoversen2 = "${PACKAGE_EXTRA_ARCHS_tune-armv8-5a} neoversen2"
20PACKAGE_EXTRA_ARCHS_tune-neoversen2-crypto = "${PACKAGE_EXTRA_ARCHS_tune-armv8-5a-crypto} neoversen2 neoversen2-crypto"
21BASE_LIB_tune-neoversen2 = "lib64"
22BASE_LIB_tune-neoversen2-crypto = "lib64"
diff --git a/meta/conf/machine/include/tune-cortexa72.inc b/meta/conf/machine/include/tune-cortexa72.inc
index b3f68ab6e3..efb71ee0a1 100644
--- a/meta/conf/machine/include/tune-cortexa72.inc
+++ b/meta/conf/machine/include/tune-cortexa72.inc
@@ -6,8 +6,12 @@ TUNE_CCARGS .= "${@bb.utils.contains('TUNE_FEATURES', 'cortexa72', ' -mcpu=corte
6require conf/machine/include/arm/arch-armv8a.inc 6require conf/machine/include/arm/arch-armv8a.inc
7 7
8# Little Endian base configs 8# Little Endian base configs
9AVAILTUNES += "cortexa72" 9AVAILTUNES += "cortexa72 cortexa72-crypto"
10ARMPKGARCH_tune-cortexa72 = "cortexa72" 10ARMPKGARCH_tune-cortexa72 = "cortexa72"
11TUNE_FEATURES_tune-cortexa72 = "${TUNE_FEATURES_tune-armv8a-crc-crypto} cortexa72" 11ARMPKGARCH_tune-cortexa72-crypto = "cortexa72"
12PACKAGE_EXTRA_ARCHS_tune-cortexa72 = "${PACKAGE_EXTRA_ARCHS_tune-armv8a-crc-crypto} cortexa72" 12TUNE_FEATURES_tune-cortexa72 = "${TUNE_FEATURES_tune-armv8a-crc} cortexa72"
13BASE_LIB_tune-cortexa72 = "lib64" 13TUNE_FEATURES_tune-cortexa72-crypto = "${TUNE_FEATURES_tune-cortexa72} crypto"
14PACKAGE_EXTRA_ARCHS_tune-cortexa72 = "${PACKAGE_EXTRA_ARCHS_tune-armv8-crc} cortexa72"
15PACKAGE_EXTRA_ARCHS_tune-cortexa72-crypto = "${PACKAGE_EXTRA_ARCHS_tune-armv8a-crc-crypto} cortexa72 cortexa72-crypto"
16BASE_LIB_tune-cortexa72 = "lib64"
17BASE_LIB_tune-cortexa72-crypto = "lib64"
diff --git a/meta/files/toolchain-shar-relocate.sh b/meta/files/toolchain-shar-relocate.sh
index 3ece04db0a..cee9adbf39 100644
--- a/meta/files/toolchain-shar-relocate.sh
+++ b/meta/files/toolchain-shar-relocate.sh
@@ -5,7 +5,7 @@ fi
5 5
6# fix dynamic loader paths in all ELF SDK binaries 6# fix dynamic loader paths in all ELF SDK binaries
7native_sysroot=$($SUDO_EXEC cat $env_setup_script |grep 'OECORE_NATIVE_SYSROOT='|cut -d'=' -f2|tr -d '"') 7native_sysroot=$($SUDO_EXEC cat $env_setup_script |grep 'OECORE_NATIVE_SYSROOT='|cut -d'=' -f2|tr -d '"')
8dl_path=$($SUDO_EXEC find $native_sysroot/lib -name "ld-linux*") 8dl_path=$($SUDO_EXEC find $native_sysroot/lib -maxdepth 1 -name "ld-linux*")
9if [ "$dl_path" = "" ] ; then 9if [ "$dl_path" = "" ] ; then
10 echo "SDK could not be set up. Relocate script unable to find ld-linux.so. Abort!" 10 echo "SDK could not be set up. Relocate script unable to find ld-linux.so. Abort!"
11 exit 1 11 exit 1
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py
index fccbedb519..9034fcae03 100644
--- a/meta/lib/oe/patch.py
+++ b/meta/lib/oe/patch.py
@@ -4,6 +4,7 @@
4 4
5import oe.path 5import oe.path
6import oe.types 6import oe.types
7import subprocess
7 8
8class NotFoundError(bb.BBHandledException): 9class NotFoundError(bb.BBHandledException):
9 def __init__(self, path): 10 def __init__(self, path):
@@ -25,7 +26,6 @@ class CmdError(bb.BBHandledException):
25 26
26def runcmd(args, dir = None): 27def runcmd(args, dir = None):
27 import pipes 28 import pipes
28 import subprocess
29 29
30 if dir: 30 if dir:
31 olddir = os.path.abspath(os.curdir) 31 olddir = os.path.abspath(os.curdir)
@@ -56,6 +56,7 @@ def runcmd(args, dir = None):
56 if dir: 56 if dir:
57 os.chdir(olddir) 57 os.chdir(olddir)
58 58
59
59class PatchError(Exception): 60class PatchError(Exception):
60 def __init__(self, msg): 61 def __init__(self, msg):
61 self.msg = msg 62 self.msg = msg
@@ -298,6 +299,24 @@ class GitApplyTree(PatchTree):
298 PatchTree.__init__(self, dir, d) 299 PatchTree.__init__(self, dir, d)
299 self.commituser = d.getVar('PATCH_GIT_USER_NAME') 300 self.commituser = d.getVar('PATCH_GIT_USER_NAME')
300 self.commitemail = d.getVar('PATCH_GIT_USER_EMAIL') 301 self.commitemail = d.getVar('PATCH_GIT_USER_EMAIL')
302 if not self._isInitialized():
303 self._initRepo()
304
305 def _isInitialized(self):
306 cmd = "git rev-parse --show-toplevel"
307 try:
308 output = runcmd(cmd.split(), self.dir).strip()
309 except CmdError as err:
310 ## runcmd returned non-zero which most likely means 128
311 ## Not a git directory
312 return False
313 ## Make sure repo is in builddir to not break top-level git repos
314 return os.path.samefile(output, self.dir)
315
316 def _initRepo(self):
317 runcmd("git init".split(), self.dir)
318 runcmd("git add .".split(), self.dir)
319 runcmd("git commit -a --allow-empty -m bitbake_patching_started".split(), self.dir)
301 320
302 @staticmethod 321 @staticmethod
303 def extractPatchHeader(patchfile): 322 def extractPatchHeader(patchfile):
diff --git a/meta/lib/oe/reproducible.py b/meta/lib/oe/reproducible.py
index 204b9bd734..0938e4cb39 100644
--- a/meta/lib/oe/reproducible.py
+++ b/meta/lib/oe/reproducible.py
@@ -41,7 +41,7 @@ def find_git_folder(d, sourcedir):
41 for root, dirs, files in os.walk(workdir, topdown=True): 41 for root, dirs, files in os.walk(workdir, topdown=True):
42 dirs[:] = [d for d in dirs if d not in exclude] 42 dirs[:] = [d for d in dirs if d not in exclude]
43 if '.git' in dirs: 43 if '.git' in dirs:
44 return root 44 return os.path.join(root, ".git")
45 45
46 bb.warn("Failed to find a git repository in WORKDIR: %s" % workdir) 46 bb.warn("Failed to find a git repository in WORKDIR: %s" % workdir)
47 return None 47 return None
diff --git a/meta/lib/oe/sdk.py b/meta/lib/oe/sdk.py
index 37b59afd1a..27347667e8 100644
--- a/meta/lib/oe/sdk.py
+++ b/meta/lib/oe/sdk.py
@@ -115,6 +115,10 @@ def sdk_list_installed_packages(d, target, rootfs_dir=None):
115 115
116 rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True] 116 rootfs_dir = [sdk_output, os.path.join(sdk_output, target_path)][target is True]
117 117
118 if target is False:
119 ipkgconf_sdk_target = d.getVar("IPKGCONF_SDK")
120 d.setVar("IPKGCONF_TARGET", ipkgconf_sdk_target)
121
118 img_type = d.getVar('IMAGE_PKGTYPE') 122 img_type = d.getVar('IMAGE_PKGTYPE')
119 import importlib 123 import importlib
120 cls = importlib.import_module('oe.package_manager.' + img_type) 124 cls = importlib.import_module('oe.package_manager.' + img_type)
diff --git a/meta/lib/oeqa/runtime/cases/parselogs.py b/meta/lib/oeqa/runtime/cases/parselogs.py
index 01b633d89e..c842f95c34 100644
--- a/meta/lib/oeqa/runtime/cases/parselogs.py
+++ b/meta/lib/oeqa/runtime/cases/parselogs.py
@@ -302,7 +302,7 @@ class ParseLogsTest(OERuntimeTestCase):
302 grepcmd = 'grep ' 302 grepcmd = 'grep '
303 grepcmd += '-Ei "' 303 grepcmd += '-Ei "'
304 for error in errors: 304 for error in errors:
305 grepcmd += '\<' + error + '\>' + '|' 305 grepcmd += r'\<' + error + r'\>' + '|'
306 grepcmd = grepcmd[:-1] 306 grepcmd = grepcmd[:-1]
307 grepcmd += '" ' + str(log) + " | grep -Eiv \'" 307 grepcmd += '" ' + str(log) + " | grep -Eiv \'"
308 308
@@ -313,13 +313,13 @@ class ParseLogsTest(OERuntimeTestCase):
313 errorlist = ignore_errors['default'] 313 errorlist = ignore_errors['default']
314 314
315 for ignore_error in errorlist: 315 for ignore_error in errorlist:
316 ignore_error = ignore_error.replace('(', '\(') 316 ignore_error = ignore_error.replace('(', r'\(')
317 ignore_error = ignore_error.replace(')', '\)') 317 ignore_error = ignore_error.replace(')', r'\)')
318 ignore_error = ignore_error.replace("'", '.') 318 ignore_error = ignore_error.replace("'", '.')
319 ignore_error = ignore_error.replace('?', '\?') 319 ignore_error = ignore_error.replace('?', r'\?')
320 ignore_error = ignore_error.replace('[', '\[') 320 ignore_error = ignore_error.replace('[', r'\[')
321 ignore_error = ignore_error.replace(']', '\]') 321 ignore_error = ignore_error.replace(']', r'\]')
322 ignore_error = ignore_error.replace('*', '\*') 322 ignore_error = ignore_error.replace('*', r'\*')
323 ignore_error = ignore_error.replace('0-9', '[0-9]') 323 ignore_error = ignore_error.replace('0-9', '[0-9]')
324 grepcmd += ignore_error + '|' 324 grepcmd += ignore_error + '|'
325 grepcmd = grepcmd[:-1] 325 grepcmd = grepcmd[:-1]
diff --git a/meta/lib/oeqa/selftest/cases/bbtests.py b/meta/lib/oeqa/selftest/cases/bbtests.py
index b932d5276b..4187cb840a 100644
--- a/meta/lib/oeqa/selftest/cases/bbtests.py
+++ b/meta/lib/oeqa/selftest/cases/bbtests.py
@@ -163,7 +163,7 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\"
163""") 163""")
164 self.track_for_cleanup(os.path.join(self.builddir, "download-selftest")) 164 self.track_for_cleanup(os.path.join(self.builddir, "download-selftest"))
165 165
166 data = 'SRC_URI = "${GNU_MIRROR}/aspell/aspell-${PV}.tar.gz;downloadfilename=test-aspell.tar.gz"' 166 data = 'SRC_URI = "https://downloads.yoctoproject.org/mirror/sources/aspell-${PV}.tar.gz;downloadfilename=test-aspell.tar.gz"'
167 self.write_recipeinc('aspell', data) 167 self.write_recipeinc('aspell', data)
168 result = bitbake('-f -c fetch aspell', ignore_status=True) 168 result = bitbake('-f -c fetch aspell', ignore_status=True)
169 self.delete_recipeinc('aspell') 169 self.delete_recipeinc('aspell')
@@ -300,3 +300,32 @@ INHERIT_remove = \"report-error\"
300 300
301 test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe) 301 test_recipe_summary_after = get_bb_var('SUMMARY', test_recipe)
302 self.assertEqual(expected_recipe_summary, test_recipe_summary_after) 302 self.assertEqual(expected_recipe_summary, test_recipe_summary_after)
303
304 def test_git_patchtool(self):
305 """ PATCHTOOL=git should work with non-git sources like tarballs
306 test recipe for the test must NOT containt git:// repository in SRC_URI
307 """
308 test_recipe = "man-db"
309 self.write_recipeinc(test_recipe, 'PATCHTOOL=\"git\"')
310 src = get_bb_var("SRC_URI",test_recipe)
311 gitscm = re.search("git://", src)
312 self.assertFalse(gitscm, "test_git_patchtool pre-condition failed: {} test recipe contains git repo!".format(test_recipe))
313 result = bitbake('{} -c patch'.format(test_recipe), ignore_status=False)
314 fatal = re.search("fatal: not a git repository (or any of the parent directories)", result.output)
315 self.assertFalse(fatal, "Failed to patch using PATCHTOOL=\"git\"")
316 self.delete_recipeinc(test_recipe)
317 bitbake('-cclean {}'.format(test_recipe))
318
319 def test_git_patchtool2(self):
320 """ Test if PATCHTOOL=git works with git repo and doesn't reinitialize it
321 """
322 test_recipe = "gitrepotest"
323 src = get_bb_var("SRC_URI",test_recipe)
324 gitscm = re.search("git://", src)
325 self.assertTrue(gitscm, "test_git_patchtool pre-condition failed: {} test recipe doesn't contains git repo!".format(test_recipe))
326 result = bitbake('{} -c patch'.format(test_recipe), ignore_status=False)
327 srcdir = get_bb_var('S', test_recipe)
328 result = runCmd("git log", cwd = srcdir)
329 self.assertFalse("bitbake_patching_started" in result.output, msg = "Repository has been reinitialized. {}".format(srcdir))
330 self.delete_recipeinc(test_recipe)
331 bitbake('-cclean {}'.format(test_recipe))
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 66e326253e..7ac1fcfbeb 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -442,6 +442,7 @@ class DevtoolAddTests(DevtoolBase):
442 tempdir = tempfile.mkdtemp(prefix='devtoolqa') 442 tempdir = tempfile.mkdtemp(prefix='devtoolqa')
443 self.track_for_cleanup(tempdir) 443 self.track_for_cleanup(tempdir)
444 url = 'gitsm://git.yoctoproject.org/mraa' 444 url = 'gitsm://git.yoctoproject.org/mraa'
445 url_branch = '%s;branch=master' % url
445 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d' 446 checkrev = 'ae127b19a50aa54255e4330ccfdd9a5d058e581d'
446 testrecipe = 'mraa' 447 testrecipe = 'mraa'
447 srcdir = os.path.join(tempdir, testrecipe) 448 srcdir = os.path.join(tempdir, testrecipe)
@@ -462,7 +463,7 @@ class DevtoolAddTests(DevtoolBase):
462 checkvars = {} 463 checkvars = {}
463 checkvars['S'] = '${WORKDIR}/git' 464 checkvars['S'] = '${WORKDIR}/git'
464 checkvars['PV'] = '1.0+git${SRCPV}' 465 checkvars['PV'] = '1.0+git${SRCPV}'
465 checkvars['SRC_URI'] = url 466 checkvars['SRC_URI'] = url_branch
466 checkvars['SRCREV'] = '${AUTOREV}' 467 checkvars['SRCREV'] = '${AUTOREV}'
467 self._test_recipe_contents(recipefile, checkvars, []) 468 self._test_recipe_contents(recipefile, checkvars, [])
468 # Try with revision and version specified 469 # Try with revision and version specified
@@ -481,7 +482,7 @@ class DevtoolAddTests(DevtoolBase):
481 checkvars = {} 482 checkvars = {}
482 checkvars['S'] = '${WORKDIR}/git' 483 checkvars['S'] = '${WORKDIR}/git'
483 checkvars['PV'] = '1.5+git${SRCPV}' 484 checkvars['PV'] = '1.5+git${SRCPV}'
484 checkvars['SRC_URI'] = url 485 checkvars['SRC_URI'] = url_branch
485 checkvars['SRCREV'] = checkrev 486 checkvars['SRCREV'] = checkrev
486 self._test_recipe_contents(recipefile, checkvars, []) 487 self._test_recipe_contents(recipefile, checkvars, [])
487 488
diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py
index 3621492998..4f283cdc03 100644
--- a/meta/lib/oeqa/selftest/cases/recipetool.py
+++ b/meta/lib/oeqa/selftest/cases/recipetool.py
@@ -375,7 +375,7 @@ class RecipetoolTests(RecipetoolBase):
375 temprecipe = os.path.join(self.tempdir, 'recipe') 375 temprecipe = os.path.join(self.tempdir, 'recipe')
376 os.makedirs(temprecipe) 376 os.makedirs(temprecipe)
377 pv = '1.7.3.0' 377 pv = '1.7.3.0'
378 srcuri = 'http://www.dest-unreach.org/socat/download/socat-%s.tar.bz2' % pv 378 srcuri = 'http://www.dest-unreach.org/socat/download/Archive/socat-%s.tar.bz2' % pv
379 result = runCmd('recipetool create %s -o %s' % (srcuri, temprecipe)) 379 result = runCmd('recipetool create %s -o %s' % (srcuri, temprecipe))
380 dirlist = os.listdir(temprecipe) 380 dirlist = os.listdir(temprecipe)
381 if len(dirlist) > 1: 381 if len(dirlist) > 1:
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index a62757399b..546dc91120 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -114,8 +114,9 @@ def compare_file(reference, test, diffutils_sysroot):
114 result.status = SAME 114 result.status = SAME
115 return result 115 return result
116 116
117def run_diffoscope(a_dir, b_dir, html_dir, **kwargs): 117def run_diffoscope(a_dir, b_dir, html_dir, max_report_size=0, **kwargs):
118 return runCmd(['diffoscope', '--no-default-limits', '--exclude-directory-metadata', 'yes', '--html-dir', html_dir, a_dir, b_dir], 118 return runCmd(['diffoscope', '--no-default-limits', '--max-report-size', str(max_report_size),
119 '--exclude-directory-metadata', 'yes', '--html-dir', html_dir, a_dir, b_dir],
119 **kwargs) 120 **kwargs)
120 121
121class DiffoscopeTests(OESelftestTestCase): 122class DiffoscopeTests(OESelftestTestCase):
@@ -145,6 +146,9 @@ class ReproducibleTests(OESelftestTestCase):
145 146
146 package_classes = ['deb', 'ipk', 'rpm'] 147 package_classes = ['deb', 'ipk', 'rpm']
147 148
149 # Maximum report size, in bytes
150 max_report_size = 250 * 1024 * 1024
151
148 # targets are the things we want to test the reproducibility of 152 # targets are the things we want to test the reproducibility of
149 targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world'] 153 targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world']
150 # sstate targets are things to pull from sstate to potentially cut build/debugging time 154 # sstate targets are things to pull from sstate to potentially cut build/debugging time
@@ -321,7 +325,7 @@ class ReproducibleTests(OESelftestTestCase):
321 # Copy jquery to improve the diffoscope output usability 325 # Copy jquery to improve the diffoscope output usability
322 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js')) 326 self.copy_file(os.path.join(jquery_sysroot, 'usr/share/javascript/jquery/jquery.min.js'), os.path.join(package_html_dir, 'jquery.js'))
323 327
324 run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, 328 run_diffoscope('reproducibleA', 'reproducibleB', package_html_dir, max_report_size=self.max_report_size,
325 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir) 329 native_sysroot=diffoscope_sysroot, ignore_status=True, cwd=package_dir)
326 330
327 if fails: 331 if fails:
diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py
index b20c5b427b..f9649339e5 100644
--- a/meta/lib/oeqa/selftest/cases/runtime_test.py
+++ b/meta/lib/oeqa/selftest/cases/runtime_test.py
@@ -185,6 +185,10 @@ class TestImage(OESelftestTestCase):
185 self.skipTest('virgl isn\'t working with Debian 9') 185 self.skipTest('virgl isn\'t working with Debian 9')
186 if distro and distro == 'centos-7': 186 if distro and distro == 'centos-7':
187 self.skipTest('virgl isn\'t working with Centos 7') 187 self.skipTest('virgl isn\'t working with Centos 7')
188 if distro and distro == 'centos-8':
189 self.skipTest('virgl isn\'t working with Centos 8')
190 if distro and distro == 'fedora-34':
191 self.skipTest('virgl isn\'t working with Fedora 34')
188 if distro and distro == 'opensuseleap-15.0': 192 if distro and distro == 'opensuseleap-15.0':
189 self.skipTest('virgl isn\'t working with Opensuse 15.0') 193 self.skipTest('virgl isn\'t working with Opensuse 15.0')
190 194
@@ -228,6 +232,9 @@ class TestImage(OESelftestTestCase):
228 dripath = subprocess.check_output("pkg-config --variable=dridriverdir dri", shell=True) 232 dripath = subprocess.check_output("pkg-config --variable=dridriverdir dri", shell=True)
229 except subprocess.CalledProcessError as e: 233 except subprocess.CalledProcessError as e:
230 self.skipTest("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.") 234 self.skipTest("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.")
235 distro = oe.lsb.distro_identifier()
236 if distro and distro == 'fedora-34':
237 self.skipTest('virgl isn\'t working with Fedora 34')
231 qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native') 238 qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native')
232 features = 'INHERIT += "testimage"\n' 239 features = 'INHERIT += "testimage"\n'
233 if 'opengl' not in qemu_distrofeatures: 240 if 'opengl' not in qemu_distrofeatures:
diff --git a/meta/recipes-bsp/grub/files/CVE-2021-3981-grub-mkconfig-Restore-umask-for-the-grub.cfg.patch b/meta/recipes-bsp/grub/files/CVE-2021-3981-grub-mkconfig-Restore-umask-for-the-grub.cfg.patch
new file mode 100644
index 0000000000..dae26fd8bb
--- /dev/null
+++ b/meta/recipes-bsp/grub/files/CVE-2021-3981-grub-mkconfig-Restore-umask-for-the-grub.cfg.patch
@@ -0,0 +1,49 @@
1From 0adec29674561034771c13e446069b41ef41e4d4 Mon Sep 17 00:00:00 2001
2From: Michael Chang <mchang@suse.com>
3Date: Fri, 3 Dec 2021 16:13:28 +0800
4Subject: [PATCH] grub-mkconfig: Restore umask for the grub.cfg
5
6The commit ab2e53c8a (grub-mkconfig: Honor a symlink when generating
7configuration by grub-mkconfig) has inadvertently discarded umask for
8creating grub.cfg in the process of running grub-mkconfig. The resulting
9wrong permission (0644) would allow unprivileged users to read GRUB
10configuration file content. This presents a low confidentiality risk
11as grub.cfg may contain non-secured plain-text passwords.
12
13This patch restores the missing umask and sets the creation file mode
14to 0600 preventing unprivileged access.
15
16Fixes: CVE-2021-3981
17
18Signed-off-by: Michael Chang <mchang@suse.com>
19Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
20
21Upstream-Status: Backport
22CVE: CVE-2021-3981
23
24Reference to upstream patch:
25https://git.savannah.gnu.org/cgit/grub.git/commit/?id=0adec29674561034771c13e446069b41ef41e4d4
26
27Signed-off-by: Yongxin Liu <yongxin.liu@windriver.com>
28---
29 util/grub-mkconfig.in | 3 +++
30 1 file changed, 3 insertions(+)
31
32diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
33index c3ea7612e..62335d027 100644
34--- a/util/grub-mkconfig.in
35+++ b/util/grub-mkconfig.in
36@@ -301,7 +301,10 @@ and /etc/grub.d/* files or please file a bug report with
37 exit 1
38 else
39 # none of the children aborted with error, install the new grub.cfg
40+ oldumask=$(umask)
41+ umask 077
42 cat ${grub_cfg}.new > ${grub_cfg}
43+ umask $oldumask
44 rm -f ${grub_cfg}.new
45 fi
46 fi
47--
482.31.1
49
diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc
index 3c6b434c2d..a70754e346 100644
--- a/meta/recipes-bsp/grub/grub2.inc
+++ b/meta/recipes-bsp/grub/grub2.inc
@@ -20,6 +20,7 @@ SRC_URI = "https://alpha.gnu.org/gnu/grub/grub-${REALPV}.tar.xz \
20 file://0001-grub.d-10_linux.in-add-oe-s-kernel-name.patch \ 20 file://0001-grub.d-10_linux.in-add-oe-s-kernel-name.patch \
21 file://determinism.patch \ 21 file://determinism.patch \
22 file://0001-RISC-V-Restore-the-typcast-to-long.patch \ 22 file://0001-RISC-V-Restore-the-typcast-to-long.patch \
23 file://CVE-2021-3981-grub-mkconfig-Restore-umask-for-the-grub.cfg.patch \
23" 24"
24 25
25SRC_URI[sha256sum] = "2c87f1f21e2ab50043e6cd9163c08f1b6c3a6171556bf23ff9ed65b074145484" 26SRC_URI[sha256sum] = "2c87f1f21e2ab50043e6cd9163c08f1b6c3a6171556bf23ff9ed65b074145484"
diff --git a/meta/recipes-connectivity/mobile-broadband-provider-info/mobile-broadband-provider-info_git.bb b/meta/recipes-connectivity/mobile-broadband-provider-info/mobile-broadband-provider-info_git.bb
index b4cbc1a76c..781b9216c5 100644
--- a/meta/recipes-connectivity/mobile-broadband-provider-info/mobile-broadband-provider-info_git.bb
+++ b/meta/recipes-connectivity/mobile-broadband-provider-info/mobile-broadband-provider-info_git.bb
@@ -4,11 +4,12 @@ DESCRIPTION = "Mobile Broadband Service Provider Database stores service provide
4SECTION = "network" 4SECTION = "network"
5LICENSE = "PD" 5LICENSE = "PD"
6LIC_FILES_CHKSUM = "file://COPYING;md5=87964579b2a8ece4bc6744d2dc9a8b04" 6LIC_FILES_CHKSUM = "file://COPYING;md5=87964579b2a8ece4bc6744d2dc9a8b04"
7SRCREV = "90f3fe28aa25135b7e4a54a7816388913bfd4a2a" 7
8PV = "20201225" 8SRCREV = "4cbb44a9fe26aa6f0b28beb79f9488b37c097b5e"
9PV = "20220315"
9PE = "1" 10PE = "1"
10 11
11SRC_URI = "git://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git;protocol=https;branch=master" 12SRC_URI = "git://gitlab.gnome.org/GNOME/mobile-broadband-provider-info.git;protocol=https;branch=main"
12S = "${WORKDIR}/git" 13S = "${WORKDIR}/git"
13 14
14inherit autotools 15inherit autotools
diff --git a/meta/recipes-connectivity/openssl/openssl/reproducibility.patch b/meta/recipes-connectivity/openssl/openssl/reproducibility.patch
new file mode 100644
index 0000000000..8accbc9df2
--- /dev/null
+++ b/meta/recipes-connectivity/openssl/openssl/reproducibility.patch
@@ -0,0 +1,22 @@
1Using localtime() means the output can depend on the timezone of the build machine.
2Using gmtime() is safer. For complete reproducibility use SOURCE_DATE_EPOCH if set.
3
4Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
5Upstream-Status: Pending [should be suitable]
6
7Index: openssl-3.0.1/apps/progs.pl
8===================================================================
9--- openssl-3.0.1.orig/apps/progs.pl
10+++ openssl-3.0.1/apps/progs.pl
11@@ -21,7 +21,10 @@ die "Unrecognised option, must be -C or
12 my %commands = ();
13 my $cmdre = qr/^\s*int\s+([a-z_][a-z0-9_]*)_main\(\s*int\s+argc\s*,/;
14 my $apps_openssl = shift @ARGV;
15-my $YEAR = [localtime()]->[5] + 1900;
16+my $YEAR = [gmtime()]->[5] + 1900;
17+if (defined($ENV{SOURCE_DATE_EPOCH}) && $ENV{SOURCE_DATE_EPOCH} !~ /\D/) {
18+ $YEAR = [gmtime($ENV{SOURCE_DATE_EPOCH})]->[5] + 1900;
19+}
20
21 # because the program apps/openssl has object files as sources, and
22 # they then have the corresponding C files as source, we need to chain
diff --git a/meta/recipes-connectivity/openssl/openssl_1.1.1l.bb b/meta/recipes-connectivity/openssl/openssl_1.1.1n.bb
index 9ea5c4c81f..df13abf54e 100644
--- a/meta/recipes-connectivity/openssl/openssl_1.1.1l.bb
+++ b/meta/recipes-connectivity/openssl/openssl_1.1.1n.bb
@@ -17,6 +17,7 @@ SRC_URI = "http://www.openssl.org/source/openssl-${PV}.tar.gz \
17 file://0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch \ 17 file://0001-buildinfo-strip-sysroot-and-debug-prefix-map-from-co.patch \
18 file://afalg.patch \ 18 file://afalg.patch \
19 file://reproducible.patch \ 19 file://reproducible.patch \
20 file://reproducibility.patch \
20 " 21 "
21 22
22SRC_URI_append_class-nativesdk = " \ 23SRC_URI_append_class-nativesdk = " \
@@ -28,7 +29,7 @@ SRC_URI_append_riscv32 = " \
28 file://0004-Fixup-support-for-io_pgetevents_time64-syscall.patch \ 29 file://0004-Fixup-support-for-io_pgetevents_time64-syscall.patch \
29 " 30 "
30 31
31SRC_URI[sha256sum] = "0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1" 32SRC_URI[sha256sum] = "40dceb51a4f6a5275bde0e6bf20ef4b91bfc32ed57c0552e2e8e15463372b17a"
32 33
33inherit lib_package multilib_header multilib_script ptest 34inherit lib_package multilib_header multilib_script ptest
34MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash" 35MULTILIB_SCRIPTS = "${PN}-bin:${bindir}/c_rehash"
@@ -203,6 +204,7 @@ do_install_ptest () {
203 install -m755 ${B}/apps/CA.pl ${D}${PTEST_PATH}/apps 204 install -m755 ${B}/apps/CA.pl ${D}${PTEST_PATH}/apps
204 205
205 install -d ${D}${PTEST_PATH}/engines 206 install -d ${D}${PTEST_PATH}/engines
207 install -m755 ${B}/engines/dasync.so ${D}${PTEST_PATH}/engines
206 install -m755 ${B}/engines/ossltest.so ${D}${PTEST_PATH}/engines 208 install -m755 ${B}/engines/ossltest.so ${D}${PTEST_PATH}/engines
207 209
208 # seems to be needed with perl 5.32.1 210 # seems to be needed with perl 5.32.1
diff --git a/meta/recipes-connectivity/socat/socat_1.7.4.1.bb b/meta/recipes-connectivity/socat/socat_1.7.4.1.bb
index 5a13af91bc..0a1b65a8ca 100644
--- a/meta/recipes-connectivity/socat/socat_1.7.4.1.bb
+++ b/meta/recipes-connectivity/socat/socat_1.7.4.1.bb
@@ -9,7 +9,7 @@ LICENSE = "GPL-2.0-with-OpenSSL-exception"
9LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \ 9LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263 \
10 file://README;beginline=257;endline=287;md5=82520b052f322ac2b5b3dfdc7c7eea86" 10 file://README;beginline=257;endline=287;md5=82520b052f322ac2b5b3dfdc7c7eea86"
11 11
12SRC_URI = "http://www.dest-unreach.org/socat/download/socat-${PV}.tar.bz2 \ 12SRC_URI = "http://www.dest-unreach.org/socat/download/Archive/socat-${PV}.tar.bz2 \
13" 13"
14 14
15SRC_URI[md5sum] = "36cad050ecf4981ab044c3fbd75c643f" 15SRC_URI[md5sum] = "36cad050ecf4981ab044c3fbd75c643f"
diff --git a/meta/recipes-core/busybox/busybox-inittab_1.33.0.bb b/meta/recipes-core/busybox/busybox-inittab_1.33.2.bb
index 3804f4f7b2..3804f4f7b2 100644
--- a/meta/recipes-core/busybox/busybox-inittab_1.33.0.bb
+++ b/meta/recipes-core/busybox/busybox-inittab_1.33.2.bb
diff --git a/meta/recipes-core/busybox/busybox/0001-awk-fix-CVEs.patch b/meta/recipes-core/busybox/busybox/0001-awk-fix-CVEs.patch
new file mode 100644
index 0000000000..c07b53ebfd
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0001-awk-fix-CVEs.patch
@@ -0,0 +1,3266 @@
1From cf542caeed195af05fa6205341f829ccee53f8c2 Mon Sep 17 00:00:00 2001
2From: Chen Qi <Qi.Chen@windriver.com>
3Date: Tue, 4 Jan 2022 17:48:03 -0800
4Subject: [PATCH] awk: fix CVEs
5
6The awk CVEs is hard to be separated, thus we use the following method
7to format the current patch.
8git rev-list --reverse 1_33_2..1_34_1 -- editors/awk.c | xargs git cherry-pick
9git reset HEAD~66 && git add . && git commit
10
11CVE: CVE-2021-42378
12CVE: CVE-2021-42379
13CVE: CVE-2021-42380
14CVE: CVE-2021-42381
15CVE: CVE-2021-42382
16CVE: CVE-2021-42383
17CVE: CVE-2021-42384
18CVE: CVE-2021-42385
19CVE: CVE-2021-42386
20
21Upstream-Status: Backport
22
23Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
24---
25 editors/awk.c | 2060 +++++++++++++++++++++++-----------------
26 testsuite/awk.tests | 62 +-
27 testsuite/printf.tests | 5 +
28 3 files changed, 1264 insertions(+), 863 deletions(-)
29
30diff --git a/editors/awk.c b/editors/awk.c
31index 2c15f9e4e..f6314ac72 100644
32--- a/editors/awk.c
33+++ b/editors/awk.c
34@@ -66,6 +66,8 @@
35 #endif
36 #ifndef debug_printf_parse
37 # define debug_printf_parse(...) (fprintf(stderr, __VA_ARGS__))
38+#else
39+# define debug_parse_print_tc(...) ((void)0)
40 #endif
41
42
43@@ -91,7 +93,6 @@ enum {
44 };
45
46 #define MAXVARFMT 240
47-#define MINNVBLOCK 64
48
49 /* variable flags */
50 #define VF_NUMBER 0x0001 /* 1 = primary type is number */
51@@ -101,7 +102,7 @@ enum {
52 #define VF_USER 0x0200 /* 1 = user input (may be numeric string) */
53 #define VF_SPECIAL 0x0400 /* 1 = requires extra handling when changed */
54 #define VF_WALK 0x0800 /* 1 = variable has alloc'd x.walker list */
55-#define VF_FSTR 0x1000 /* 1 = var::string points to fstring buffer */
56+#define VF_FSTR 0x1000 /* 1 = don't free() var::string (not malloced, or is owned by something else) */
57 #define VF_CHILD 0x2000 /* 1 = function arg; x.parent points to source */
58 #define VF_DIRTY 0x4000 /* 1 = variable was set explicitly */
59
60@@ -118,8 +119,8 @@ typedef struct walker_list {
61 /* Variable */
62 typedef struct var_s {
63 unsigned type; /* flags */
64- double number;
65 char *string;
66+ double number;
67 union {
68 int aidx; /* func arg idx (for compilation stage) */
69 struct xhash_s *array; /* array ptr */
70@@ -138,6 +139,7 @@ typedef struct chain_s {
71 /* Function */
72 typedef struct func_s {
73 unsigned nargs;
74+ smallint defined;
75 struct chain_s body;
76 } func;
77
78@@ -177,7 +179,7 @@ typedef struct node_s {
79 struct node_s *n;
80 var *v;
81 int aidx;
82- char *new_progname;
83+ const char *new_progname;
84 regex_t *re;
85 } l;
86 union {
87@@ -190,91 +192,120 @@ typedef struct node_s {
88 } a;
89 } node;
90
91-/* Block of temporary variables */
92-typedef struct nvblock_s {
93- int size;
94- var *pos;
95- struct nvblock_s *prev;
96- struct nvblock_s *next;
97- var nv[];
98-} nvblock;
99-
100 typedef struct tsplitter_s {
101 node n;
102 regex_t re[2];
103 } tsplitter;
104
105 /* simple token classes */
106-/* Order and hex values are very important!!! See next_token() */
107-#define TC_SEQSTART (1 << 0) /* ( */
108-#define TC_SEQTERM (1 << 1) /* ) */
109-#define TC_REGEXP (1 << 2) /* /.../ */
110-#define TC_OUTRDR (1 << 3) /* | > >> */
111-#define TC_UOPPOST (1 << 4) /* unary postfix operator */
112-#define TC_UOPPRE1 (1 << 5) /* unary prefix operator */
113-#define TC_BINOPX (1 << 6) /* two-opnd operator */
114-#define TC_IN (1 << 7)
115-#define TC_COMMA (1 << 8)
116-#define TC_PIPE (1 << 9) /* input redirection pipe */
117-#define TC_UOPPRE2 (1 << 10) /* unary prefix operator */
118-#define TC_ARRTERM (1 << 11) /* ] */
119-#define TC_GRPSTART (1 << 12) /* { */
120-#define TC_GRPTERM (1 << 13) /* } */
121-#define TC_SEMICOL (1 << 14)
122-#define TC_NEWLINE (1 << 15)
123-#define TC_STATX (1 << 16) /* ctl statement (for, next...) */
124-#define TC_WHILE (1 << 17)
125-#define TC_ELSE (1 << 18)
126-#define TC_BUILTIN (1 << 19)
127+/* order and hex values are very important!!! See next_token() */
128+#define TC_LPAREN (1 << 0) /* ( */
129+#define TC_RPAREN (1 << 1) /* ) */
130+#define TC_REGEXP (1 << 2) /* /.../ */
131+#define TC_OUTRDR (1 << 3) /* | > >> */
132+#define TC_UOPPOST (1 << 4) /* unary postfix operator ++ -- */
133+#define TC_UOPPRE1 (1 << 5) /* unary prefix operator ++ -- $ */
134+#define TC_BINOPX (1 << 6) /* two-opnd operator */
135+#define TC_IN (1 << 7) /* 'in' */
136+#define TC_COMMA (1 << 8) /* , */
137+#define TC_PIPE (1 << 9) /* input redirection pipe | */
138+#define TC_UOPPRE2 (1 << 10) /* unary prefix operator + - ! */
139+#define TC_ARRTERM (1 << 11) /* ] */
140+#define TC_LBRACE (1 << 12) /* { */
141+#define TC_RBRACE (1 << 13) /* } */
142+#define TC_SEMICOL (1 << 14) /* ; */
143+#define TC_NEWLINE (1 << 15)
144+#define TC_STATX (1 << 16) /* ctl statement (for, next...) */
145+#define TC_WHILE (1 << 17) /* 'while' */
146+#define TC_ELSE (1 << 18) /* 'else' */
147+#define TC_BUILTIN (1 << 19)
148 /* This costs ~50 bytes of code.
149 * A separate class to support deprecated "length" form. If we don't need that
150 * (i.e. if we demand that only "length()" with () is valid), then TC_LENGTH
151 * can be merged with TC_BUILTIN:
152 */
153-#define TC_LENGTH (1 << 20)
154-#define TC_GETLINE (1 << 21)
155-#define TC_FUNCDECL (1 << 22) /* 'function' 'func' */
156-#define TC_BEGIN (1 << 23)
157-#define TC_END (1 << 24)
158-#define TC_EOF (1 << 25)
159-#define TC_VARIABLE (1 << 26)
160-#define TC_ARRAY (1 << 27)
161-#define TC_FUNCTION (1 << 28)
162-#define TC_STRING (1 << 29)
163-#define TC_NUMBER (1 << 30)
164-
165-#define TC_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2)
166-
167-/* combined token classes */
168-#define TC_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
169-//#define TC_UNARYOP (TC_UOPPRE | TC_UOPPOST)
170-#define TC_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
171- | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
172- | TC_SEQSTART | TC_STRING | TC_NUMBER)
173-
174-#define TC_STATEMNT (TC_STATX | TC_WHILE)
175-#define TC_OPTERM (TC_SEMICOL | TC_NEWLINE)
176+#define TC_LENGTH (1 << 20) /* 'length' */
177+#define TC_GETLINE (1 << 21) /* 'getline' */
178+#define TC_FUNCDECL (1 << 22) /* 'function' 'func' */
179+#define TC_BEGIN (1 << 23) /* 'BEGIN' */
180+#define TC_END (1 << 24) /* 'END' */
181+#define TC_EOF (1 << 25)
182+#define TC_VARIABLE (1 << 26) /* name */
183+#define TC_ARRAY (1 << 27) /* name[ */
184+#define TC_FUNCTION (1 << 28) /* name( */
185+#define TC_STRING (1 << 29) /* "..." */
186+#define TC_NUMBER (1 << 30)
187+
188+#ifndef debug_parse_print_tc
189+static void debug_parse_print_tc(uint32_t n)
190+{
191+ if (n & TC_LPAREN ) debug_printf_parse(" LPAREN" );
192+ if (n & TC_RPAREN ) debug_printf_parse(" RPAREN" );
193+ if (n & TC_REGEXP ) debug_printf_parse(" REGEXP" );
194+ if (n & TC_OUTRDR ) debug_printf_parse(" OUTRDR" );
195+ if (n & TC_UOPPOST ) debug_printf_parse(" UOPPOST" );
196+ if (n & TC_UOPPRE1 ) debug_printf_parse(" UOPPRE1" );
197+ if (n & TC_BINOPX ) debug_printf_parse(" BINOPX" );
198+ if (n & TC_IN ) debug_printf_parse(" IN" );
199+ if (n & TC_COMMA ) debug_printf_parse(" COMMA" );
200+ if (n & TC_PIPE ) debug_printf_parse(" PIPE" );
201+ if (n & TC_UOPPRE2 ) debug_printf_parse(" UOPPRE2" );
202+ if (n & TC_ARRTERM ) debug_printf_parse(" ARRTERM" );
203+ if (n & TC_LBRACE ) debug_printf_parse(" LBRACE" );
204+ if (n & TC_RBRACE ) debug_printf_parse(" RBRACE" );
205+ if (n & TC_SEMICOL ) debug_printf_parse(" SEMICOL" );
206+ if (n & TC_NEWLINE ) debug_printf_parse(" NEWLINE" );
207+ if (n & TC_STATX ) debug_printf_parse(" STATX" );
208+ if (n & TC_WHILE ) debug_printf_parse(" WHILE" );
209+ if (n & TC_ELSE ) debug_printf_parse(" ELSE" );
210+ if (n & TC_BUILTIN ) debug_printf_parse(" BUILTIN" );
211+ if (n & TC_LENGTH ) debug_printf_parse(" LENGTH" );
212+ if (n & TC_GETLINE ) debug_printf_parse(" GETLINE" );
213+ if (n & TC_FUNCDECL) debug_printf_parse(" FUNCDECL");
214+ if (n & TC_BEGIN ) debug_printf_parse(" BEGIN" );
215+ if (n & TC_END ) debug_printf_parse(" END" );
216+ if (n & TC_EOF ) debug_printf_parse(" EOF" );
217+ if (n & TC_VARIABLE) debug_printf_parse(" VARIABLE");
218+ if (n & TC_ARRAY ) debug_printf_parse(" ARRAY" );
219+ if (n & TC_FUNCTION) debug_printf_parse(" FUNCTION");
220+ if (n & TC_STRING ) debug_printf_parse(" STRING" );
221+ if (n & TC_NUMBER ) debug_printf_parse(" NUMBER" );
222+}
223+#endif
224+
225+/* combined token classes ("token [class] sets") */
226+#define TS_UOPPRE (TC_UOPPRE1 | TC_UOPPRE2)
227+
228+#define TS_BINOP (TC_BINOPX | TC_COMMA | TC_PIPE | TC_IN)
229+//#define TS_UNARYOP (TS_UOPPRE | TC_UOPPOST)
230+#define TS_OPERAND (TC_VARIABLE | TC_ARRAY | TC_FUNCTION \
231+ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
232+ | TC_LPAREN | TC_STRING | TC_NUMBER)
233+
234+#define TS_LVALUE (TC_VARIABLE | TC_ARRAY)
235+#define TS_STATEMNT (TC_STATX | TC_WHILE)
236
237 /* word tokens, cannot mean something else if not expected */
238-#define TC_WORD (TC_IN | TC_STATEMNT | TC_ELSE \
239- | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
240- | TC_FUNCDECL | TC_BEGIN | TC_END)
241+#define TS_WORD (TC_IN | TS_STATEMNT | TC_ELSE \
242+ | TC_BUILTIN | TC_LENGTH | TC_GETLINE \
243+ | TC_FUNCDECL | TC_BEGIN | TC_END)
244
245 /* discard newlines after these */
246-#define TC_NOTERM (TC_COMMA | TC_GRPSTART | TC_GRPTERM \
247- | TC_BINOP | TC_OPTERM)
248+#define TS_NOTERM (TS_BINOP | TC_COMMA | TC_LBRACE | TC_RBRACE \
249+ | TC_SEMICOL | TC_NEWLINE)
250
251 /* what can expression begin with */
252-#define TC_OPSEQ (TC_OPERAND | TC_UOPPRE | TC_REGEXP)
253+#define TS_OPSEQ (TS_OPERAND | TS_UOPPRE | TC_REGEXP)
254 /* what can group begin with */
255-#define TC_GRPSEQ (TC_OPSEQ | TC_OPTERM | TC_STATEMNT | TC_GRPSTART)
256+#define TS_GRPSEQ (TS_OPSEQ | TS_STATEMNT \
257+ | TC_SEMICOL | TC_NEWLINE | TC_LBRACE)
258
259-/* if previous token class is CONCAT1 and next is CONCAT2, concatenation */
260+/* if previous token class is CONCAT_L and next is CONCAT_R, concatenation */
261 /* operator is inserted between them */
262-#define TC_CONCAT1 (TC_VARIABLE | TC_ARRTERM | TC_SEQTERM \
263+#define TS_CONCAT_L (TC_VARIABLE | TC_ARRTERM | TC_RPAREN \
264 | TC_STRING | TC_NUMBER | TC_UOPPOST \
265 | TC_LENGTH)
266-#define TC_CONCAT2 (TC_OPERAND | TC_UOPPRE)
267+#define TS_CONCAT_R (TS_OPERAND | TS_UOPPRE)
268
269 #define OF_RES1 0x010000
270 #define OF_RES2 0x020000
271@@ -284,13 +315,12 @@ typedef struct tsplitter_s {
272 #define OF_CHECKED 0x200000
273 #define OF_REQUIRED 0x400000
274
275-
276 /* combined operator flags */
277 #define xx 0
278 #define xV OF_RES2
279 #define xS (OF_RES2 | OF_STR2)
280 #define Vx OF_RES1
281-#define Rx (OF_RES1 | OF_NUM1 | OF_REQUIRED)
282+#define Rx OF_REQUIRED
283 #define VV (OF_RES1 | OF_RES2)
284 #define Nx (OF_RES1 | OF_NUM1)
285 #define NV (OF_RES1 | OF_NUM1 | OF_RES2)
286@@ -302,8 +332,7 @@ typedef struct tsplitter_s {
287 #define OPNMASK 0x007F
288
289 /* operator priority is a highest byte (even: r->l, odd: l->r grouping)
290- * For builtins it has different meaning: n n s3 s2 s1 v3 v2 v1,
291- * n - min. number of args, vN - resolve Nth arg to var, sN - resolve to string
292+ * (for builtins it has different meaning)
293 */
294 #undef P
295 #undef PRIMASK
296@@ -313,10 +342,8 @@ typedef struct tsplitter_s {
297 #define PRIMASK2 0x7E000000
298
299 /* Operation classes */
300-
301 #define SHIFT_TIL_THIS 0x0600
302 #define RECUR_FROM_THIS 0x1000
303-
304 enum {
305 OC_DELETE = 0x0100, OC_EXEC = 0x0200, OC_NEWSOURCE = 0x0300,
306 OC_PRINT = 0x0400, OC_PRINTF = 0x0500, OC_WALKINIT = 0x0600,
307@@ -358,8 +385,8 @@ enum {
308 #define NTCC '\377'
309
310 static const char tokenlist[] ALIGN1 =
311- "\1(" NTC /* TC_SEQSTART */
312- "\1)" NTC /* TC_SEQTERM */
313+ "\1(" NTC /* TC_LPAREN */
314+ "\1)" NTC /* TC_RPAREN */
315 "\1/" NTC /* TC_REGEXP */
316 "\2>>" "\1>" "\1|" NTC /* TC_OUTRDR */
317 "\2++" "\2--" NTC /* TC_UOPPOST */
318@@ -376,8 +403,8 @@ static const char tokenlist[] ALIGN1 =
319 "\1|" NTC /* TC_PIPE */
320 "\1+" "\1-" "\1!" NTC /* TC_UOPPRE2 */
321 "\1]" NTC /* TC_ARRTERM */
322- "\1{" NTC /* TC_GRPSTART */
323- "\1}" NTC /* TC_GRPTERM */
324+ "\1{" NTC /* TC_LBRACE */
325+ "\1}" NTC /* TC_RBRACE */
326 "\1;" NTC /* TC_SEMICOL */
327 "\1\n" NTC /* TC_NEWLINE */
328 "\2if" "\2do" "\3for" "\5break" /* TC_STATX */
329@@ -391,7 +418,7 @@ static const char tokenlist[] ALIGN1 =
330 "\5close" "\6system" "\6fflush" "\5atan2"
331 "\3cos" "\3exp" "\3int" "\3log"
332 "\4rand" "\3sin" "\4sqrt" "\5srand"
333- "\6gensub" "\4gsub" "\5index" /* "\6length" was here */
334+ "\6gensub" "\4gsub" "\5index" /* "\6length" was here */
335 "\5match" "\5split" "\7sprintf" "\3sub"
336 "\6substr" "\7systime" "\10strftime" "\6mktime"
337 "\7tolower" "\7toupper" NTC
338@@ -403,25 +430,32 @@ static const char tokenlist[] ALIGN1 =
339 /* compiler adds trailing "\0" */
340 ;
341
342-#define OC_B OC_BUILTIN
343-
344 static const uint32_t tokeninfo[] ALIGN4 = {
345 0,
346 0,
347- OC_REGEXP,
348+#define TI_REGEXP OC_REGEXP
349+ TI_REGEXP,
350 xS|'a', xS|'w', xS|'|',
351 OC_UNARY|xV|P(9)|'p', OC_UNARY|xV|P(9)|'m',
352- OC_UNARY|xV|P(9)|'P', OC_UNARY|xV|P(9)|'M', OC_FIELD|xV|P(5),
353+#define TI_PREINC (OC_UNARY|xV|P(9)|'P')
354+#define TI_PREDEC (OC_UNARY|xV|P(9)|'M')
355+ TI_PREINC, TI_PREDEC, OC_FIELD|xV|P(5),
356 OC_COMPARE|VV|P(39)|5, OC_MOVE|VV|P(74), OC_REPLACE|NV|P(74)|'+', OC_REPLACE|NV|P(74)|'-',
357 OC_REPLACE|NV|P(74)|'*', OC_REPLACE|NV|P(74)|'/', OC_REPLACE|NV|P(74)|'%', OC_REPLACE|NV|P(74)|'&',
358 OC_BINARY|NV|P(29)|'+', OC_BINARY|NV|P(29)|'-', OC_REPLACE|NV|P(74)|'&', OC_BINARY|NV|P(15)|'&',
359 OC_BINARY|NV|P(25)|'/', OC_BINARY|NV|P(25)|'%', OC_BINARY|NV|P(15)|'&', OC_BINARY|NV|P(25)|'*',
360 OC_COMPARE|VV|P(39)|4, OC_COMPARE|VV|P(39)|3, OC_COMPARE|VV|P(39)|0, OC_COMPARE|VV|P(39)|1,
361- OC_COMPARE|VV|P(39)|2, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55),
362- OC_LOR|Vx|P(59), OC_TERNARY|Vx|P(64)|'?', OC_COLON|xx|P(67)|':',
363- OC_IN|SV|P(49), /* TC_IN */
364- OC_COMMA|SS|P(80),
365- OC_PGETLINE|SV|P(37),
366+#define TI_LESS (OC_COMPARE|VV|P(39)|2)
367+ TI_LESS, OC_MATCH|Sx|P(45)|'!', OC_MATCH|Sx|P(45)|'~', OC_LAND|Vx|P(55),
368+#define TI_TERNARY (OC_TERNARY|Vx|P(64)|'?')
369+#define TI_COLON (OC_COLON|xx|P(67)|':')
370+ OC_LOR|Vx|P(59), TI_TERNARY, TI_COLON,
371+#define TI_IN (OC_IN|SV|P(49))
372+ TI_IN,
373+#define TI_COMMA (OC_COMMA|SS|P(80))
374+ TI_COMMA,
375+#define TI_PGETLINE (OC_PGETLINE|SV|P(37))
376+ TI_PGETLINE,
377 OC_UNARY|xV|P(19)|'+', OC_UNARY|xV|P(19)|'-', OC_UNARY|xV|P(19)|'!',
378 0, /* ] */
379 0,
380@@ -434,20 +468,45 @@ static const uint32_t tokeninfo[] ALIGN4 = {
381 OC_RETURN|Vx, OC_EXIT|Nx,
382 ST_WHILE,
383 0, /* else */
384- OC_B|B_an|P(0x83), OC_B|B_co|P(0x41), OC_B|B_ls|P(0x83), OC_B|B_or|P(0x83),
385- OC_B|B_rs|P(0x83), OC_B|B_xo|P(0x83),
386- OC_FBLTIN|Sx|F_cl, OC_FBLTIN|Sx|F_sy, OC_FBLTIN|Sx|F_ff, OC_B|B_a2|P(0x83),
387- OC_FBLTIN|Nx|F_co, OC_FBLTIN|Nx|F_ex, OC_FBLTIN|Nx|F_in, OC_FBLTIN|Nx|F_lg,
388- OC_FBLTIN|F_rn, OC_FBLTIN|Nx|F_si, OC_FBLTIN|Nx|F_sq, OC_FBLTIN|Nx|F_sr,
389- OC_B|B_ge|P(0xd6), OC_B|B_gs|P(0xb6), OC_B|B_ix|P(0x9b), /* OC_FBLTIN|Sx|F_le, was here */
390- OC_B|B_ma|P(0x89), OC_B|B_sp|P(0x8b), OC_SPRINTF, OC_B|B_su|P(0xb6),
391- OC_B|B_ss|P(0x8f), OC_FBLTIN|F_ti, OC_B|B_ti|P(0x0b), OC_B|B_mt|P(0x0b),
392- OC_B|B_lo|P(0x49), OC_B|B_up|P(0x49),
393- OC_FBLTIN|Sx|F_le, /* TC_LENGTH */
394- OC_GETLINE|SV|P(0),
395- 0, 0,
396- 0,
397- 0 /* TC_END */
398+// OC_B's are builtins with enforced minimum number of arguments (two upper bits).
399+// Highest byte bit pattern: nn s3s2s1 v3v2v1
400+// nn - min. number of args, sN - resolve Nth arg to string, vN - resolve to var
401+// OC_F's are builtins with zero or one argument.
402+// |Rx| enforces that arg is present for: system, close, cos, sin, exp, int, log, sqrt
403+// Check for no args is present in builtins' code (not in this table): rand, systime
404+// Have one _optional_ arg: fflush, srand, length
405+#define OC_B OC_BUILTIN
406+#define OC_F OC_FBLTIN
407+#define A1 P(0x40) /*one arg*/
408+#define A2 P(0x80) /*two args*/
409+#define A3 P(0xc0) /*three args*/
410+#define __v P(1)
411+#define _vv P(3)
412+#define __s__v P(9)
413+#define __s_vv P(0x0b)
414+#define __svvv P(0x0f)
415+#define _ss_vv P(0x1b)
416+#define _s_vv_ P(0x16)
417+#define ss_vv_ P(0x36)
418+ OC_B|B_an|_vv|A2, OC_B|B_co|__v|A1, OC_B|B_ls|_vv|A2, OC_B|B_or|_vv|A2, // and compl lshift or
419+ OC_B|B_rs|_vv|A2, OC_B|B_xo|_vv|A2, // rshift xor
420+ OC_F|F_cl|Sx|Rx, OC_F|F_sy|Sx|Rx, OC_F|F_ff|Sx, OC_B|B_a2|_vv|A2, // close system fflush atan2
421+ OC_F|F_co|Nx|Rx, OC_F|F_ex|Nx|Rx, OC_F|F_in|Nx|Rx, OC_F|F_lg|Nx|Rx, // cos exp int log
422+ OC_F|F_rn, OC_F|F_si|Nx|Rx, OC_F|F_sq|Nx|Rx, OC_F|F_sr|Nx, // rand sin sqrt srand
423+ OC_B|B_ge|_s_vv_|A3,OC_B|B_gs|ss_vv_|A2,OC_B|B_ix|_ss_vv|A2, // gensub gsub index /*length was here*/
424+ OC_B|B_ma|__s__v|A2,OC_B|B_sp|__s_vv|A2,OC_SPRINTF, OC_B|B_su|ss_vv_|A2,// match split sprintf sub
425+ OC_B|B_ss|__svvv|A2,OC_F|F_ti, OC_B|B_ti|__s_vv, OC_B|B_mt|__s_vv, // substr systime strftime mktime
426+ OC_B|B_lo|__s__v|A1,OC_B|B_up|__s__v|A1, // tolower toupper
427+ OC_F|F_le|Sx, // length
428+ OC_GETLINE|SV, // getline
429+ 0, 0, // func function
430+ 0, // BEGIN
431+ 0 // END
432+#undef A1
433+#undef A2
434+#undef A3
435+#undef OC_B
436+#undef OC_F
437 };
438
439 /* internal variable names and their initial values */
440@@ -488,21 +547,29 @@ struct globals {
441 chain *seq;
442 node *break_ptr, *continue_ptr;
443 rstream *iF;
444- xhash *vhash, *ahash, *fdhash, *fnhash;
445+ xhash *ahash; /* argument names, used only while parsing function bodies */
446+ xhash *fnhash; /* function names, used only in parsing stage */
447+ xhash *vhash; /* variables and arrays */
448+ //xhash *fdhash; /* file objects, used only in execution stage */
449+ //we are reusing ahash as fdhash, via define (see later)
450 const char *g_progname;
451 int g_lineno;
452 int nfields;
453 int maxfields; /* used in fsrealloc() only */
454 var *Fields;
455- nvblock *g_cb;
456 char *g_pos;
457- char *g_buf;
458+ char g_saved_ch;
459 smallint icase;
460 smallint exiting;
461 smallint nextrec;
462 smallint nextfile;
463 smallint is_f0_split;
464 smallint t_rollback;
465+
466+ /* former statics from various functions */
467+ smallint next_token__concat_inserted;
468+ uint32_t next_token__save_tclass;
469+ uint32_t next_token__save_info;
470 };
471 struct globals2 {
472 uint32_t t_info; /* often used */
473@@ -515,32 +582,35 @@ struct globals2 {
474 /* former statics from various functions */
475 char *split_f0__fstrings;
476
477- uint32_t next_token__save_tclass;
478- uint32_t next_token__save_info;
479- uint32_t next_token__ltclass;
480- smallint next_token__concat_inserted;
481-
482- smallint next_input_file__files_happen;
483 rstream next_input_file__rsm;
484+ smallint next_input_file__files_happen;
485+
486+ smalluint exitcode;
487
488- var *evaluate__fnargs;
489 unsigned evaluate__seed;
490+ var *evaluate__fnargs;
491 regex_t evaluate__sreg;
492
493- var ptest__v;
494+ var ptest__tmpvar;
495+ var awk_printf__tmpvar;
496+ var as_regex__tmpvar;
497+ var exit__tmpvar;
498+ var main__tmpvar;
499
500 tsplitter exec_builtin__tspl;
501
502 /* biggest and least used members go last */
503 tsplitter fsplitter, rsplitter;
504+
505+ char g_buf[MAXVARFMT + 1];
506 };
507 #define G1 (ptr_to_globals[-1])
508 #define G (*(struct globals2 *)ptr_to_globals)
509 /* For debug. nm --size-sort awk.o | grep -vi ' [tr] ' */
510-/*char G1size[sizeof(G1)]; - 0x74 */
511-/*char Gsize[sizeof(G)]; - 0x1c4 */
512+//char G1size[sizeof(G1)]; // 0x70
513+//char Gsize[sizeof(G)]; // 0x2f8
514 /* Trying to keep most of members accessible with short offsets: */
515-/*char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; - 0x90 */
516+//char Gofs_seed[offsetof(struct globals2, evaluate__seed)]; // 0x7c
517 #define t_double (G1.t_double )
518 #define beginseq (G1.beginseq )
519 #define mainseq (G1.mainseq )
520@@ -549,18 +619,20 @@ struct globals2 {
521 #define break_ptr (G1.break_ptr )
522 #define continue_ptr (G1.continue_ptr)
523 #define iF (G1.iF )
524-#define vhash (G1.vhash )
525 #define ahash (G1.ahash )
526-#define fdhash (G1.fdhash )
527 #define fnhash (G1.fnhash )
528+#define vhash (G1.vhash )
529+#define fdhash ahash
530+//^^^^^^^^^^^^^^^^^^ ahash is cleared after every function parsing,
531+// and ends up empty after parsing phase. Thus, we can simply reuse it
532+// for fdhash in execution stage.
533 #define g_progname (G1.g_progname )
534 #define g_lineno (G1.g_lineno )
535 #define nfields (G1.nfields )
536 #define maxfields (G1.maxfields )
537 #define Fields (G1.Fields )
538-#define g_cb (G1.g_cb )
539 #define g_pos (G1.g_pos )
540-#define g_buf (G1.g_buf )
541+#define g_saved_ch (G1.g_saved_ch )
542 #define icase (G1.icase )
543 #define exiting (G1.exiting )
544 #define nextrec (G1.nextrec )
545@@ -574,25 +646,13 @@ struct globals2 {
546 #define intvar (G.intvar )
547 #define fsplitter (G.fsplitter )
548 #define rsplitter (G.rsplitter )
549+#define g_buf (G.g_buf )
550 #define INIT_G() do { \
551 SET_PTR_TO_GLOBALS((char*)xzalloc(sizeof(G1)+sizeof(G)) + sizeof(G1)); \
552- G.next_token__ltclass = TC_OPTERM; \
553+ t_tclass = TC_NEWLINE; \
554 G.evaluate__seed = 1; \
555 } while (0)
556
557-
558-/* function prototypes */
559-static void handle_special(var *);
560-static node *parse_expr(uint32_t);
561-static void chain_group(void);
562-static var *evaluate(node *, var *);
563-static rstream *next_input_file(void);
564-static int fmt_num(char *, int, const char *, double, int);
565-static int awk_exit(int) NORETURN;
566-
567-/* ---- error handling ---- */
568-
569-static const char EMSG_INTERNAL_ERROR[] ALIGN1 = "Internal error";
570 static const char EMSG_UNEXP_EOS[] ALIGN1 = "Unexpected end of string";
571 static const char EMSG_UNEXP_TOKEN[] ALIGN1 = "Unexpected token";
572 static const char EMSG_DIV_BY_ZERO[] ALIGN1 = "Division by zero";
573@@ -604,10 +664,7 @@ static const char EMSG_UNDEF_FUNC[] ALIGN1 = "Call to undefined function";
574 static const char EMSG_NO_MATH[] ALIGN1 = "Math support is not compiled in";
575 static const char EMSG_NEGATIVE_FIELD[] ALIGN1 = "Access to negative field";
576
577-static void zero_out_var(var *vp)
578-{
579- memset(vp, 0, sizeof(*vp));
580-}
581+static int awk_exit(void) NORETURN;
582
583 static void syntax_error(const char *message) NORETURN;
584 static void syntax_error(const char *message)
585@@ -638,12 +695,40 @@ static xhash *hash_init(void)
586 return newhash;
587 }
588
589+static void hash_clear(xhash *hash)
590+{
591+ unsigned i;
592+ hash_item *hi, *thi;
593+
594+ for (i = 0; i < hash->csize; i++) {
595+ hi = hash->items[i];
596+ while (hi) {
597+ thi = hi;
598+ hi = hi->next;
599+//FIXME: this assumes that it's a hash of *variables*:
600+ free(thi->data.v.string);
601+ free(thi);
602+ }
603+ hash->items[i] = NULL;
604+ }
605+ hash->glen = hash->nel = 0;
606+}
607+
608+#if 0 //UNUSED
609+static void hash_free(xhash *hash)
610+{
611+ hash_clear(hash);
612+ free(hash->items);
613+ free(hash);
614+}
615+#endif
616+
617 /* find item in hash, return ptr to data, NULL if not found */
618-static void *hash_search(xhash *hash, const char *name)
619+static NOINLINE void *hash_search3(xhash *hash, const char *name, unsigned idx)
620 {
621 hash_item *hi;
622
623- hi = hash->items[hashidx(name) % hash->csize];
624+ hi = hash->items[idx % hash->csize];
625 while (hi) {
626 if (strcmp(hi->name, name) == 0)
627 return &hi->data;
628@@ -652,6 +737,11 @@ static void *hash_search(xhash *hash, const char *name)
629 return NULL;
630 }
631
632+static void *hash_search(xhash *hash, const char *name)
633+{
634+ return hash_search3(hash, name, hashidx(name));
635+}
636+
637 /* grow hash if it becomes too big */
638 static void hash_rebuild(xhash *hash)
639 {
640@@ -687,16 +777,17 @@ static void *hash_find(xhash *hash, const char *name)
641 unsigned idx;
642 int l;
643
644- hi = hash_search(hash, name);
645+ idx = hashidx(name);
646+ hi = hash_search3(hash, name, idx);
647 if (!hi) {
648- if (++hash->nel / hash->csize > 10)
649+ if (++hash->nel > hash->csize * 8)
650 hash_rebuild(hash);
651
652 l = strlen(name) + 1;
653 hi = xzalloc(sizeof(*hi) + l);
654 strcpy(hi->name, name);
655
656- idx = hashidx(name) % hash->csize;
657+ idx = idx % hash->csize;
658 hi->next = hash->items[idx];
659 hash->items[idx] = hi;
660 hash->glen += l;
661@@ -731,7 +822,7 @@ static void hash_remove(xhash *hash, const char *name)
662
663 static char *skip_spaces(char *p)
664 {
665- while (1) {
666+ for (;;) {
667 if (*p == '\\' && p[1] == '\n') {
668 p++;
669 t_lineno++;
670@@ -747,8 +838,10 @@ static char *skip_spaces(char *p)
671 static char *nextword(char **s)
672 {
673 char *p = *s;
674- while (*(*s)++ != '\0')
675+ char *q = p;
676+ while (*q++ != '\0')
677 continue;
678+ *s = q;
679 return p;
680 }
681
682@@ -811,10 +904,27 @@ static double my_strtod(char **pp)
683
684 /* -------- working with variables (set/get/copy/etc) -------- */
685
686-static xhash *iamarray(var *v)
687+static void fmt_num(const char *format, double n)
688 {
689- var *a = v;
690+ if (n == (long long)n) {
691+ snprintf(g_buf, MAXVARFMT, "%lld", (long long)n);
692+ } else {
693+ const char *s = format;
694+ char c;
695+
696+ do { c = *s; } while (c && *++s);
697+ if (strchr("diouxX", c)) {
698+ snprintf(g_buf, MAXVARFMT, format, (int)n);
699+ } else if (strchr("eEfFgGaA", c)) {
700+ snprintf(g_buf, MAXVARFMT, format, n);
701+ } else {
702+ syntax_error(EMSG_INV_FMT);
703+ }
704+ }
705+}
706
707+static xhash *iamarray(var *a)
708+{
709 while (a->type & VF_CHILD)
710 a = a->x.parent;
711
712@@ -825,23 +935,7 @@ static xhash *iamarray(var *v)
713 return a->x.array;
714 }
715
716-static void clear_array(xhash *array)
717-{
718- unsigned i;
719- hash_item *hi, *thi;
720-
721- for (i = 0; i < array->csize; i++) {
722- hi = array->items[i];
723- while (hi) {
724- thi = hi;
725- hi = hi->next;
726- free(thi->data.v.string);
727- free(thi);
728- }
729- array->items[i] = NULL;
730- }
731- array->glen = array->nel = 0;
732-}
733+#define clear_array(array) hash_clear(array)
734
735 /* clear a variable */
736 static var *clrvar(var *v)
737@@ -855,6 +949,8 @@ static var *clrvar(var *v)
738 return v;
739 }
740
741+static void handle_special(var *);
742+
743 /* assign string value to variable */
744 static var *setvar_p(var *v, char *value)
745 {
746@@ -901,7 +997,7 @@ static const char *getvar_s(var *v)
747 {
748 /* if v is numeric and has no cached string, convert it to string */
749 if ((v->type & (VF_NUMBER | VF_CACHED)) == VF_NUMBER) {
750- fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[CONVFMT]), v->number, TRUE);
751+ fmt_num(getvar_s(intvar[CONVFMT]), v->number);
752 v->string = xstrdup(g_buf);
753 v->type |= VF_CACHED;
754 }
755@@ -920,6 +1016,7 @@ static double getvar_i(var *v)
756 v->number = my_strtod(&s);
757 debug_printf_eval("%f (s:'%s')\n", v->number, s);
758 if (v->type & VF_USER) {
759+//TODO: skip_spaces() also skips backslash+newline, is it intended here?
760 s = skip_spaces(s);
761 if (*s != '\0')
762 v->type &= ~VF_USER;
763@@ -981,94 +1078,28 @@ static int istrue(var *v)
764 return (v->string && v->string[0]);
765 }
766
767-/* temporary variables allocator. Last allocated should be first freed */
768-static var *nvalloc(int n)
769-{
770- nvblock *pb = NULL;
771- var *v, *r;
772- int size;
773-
774- while (g_cb) {
775- pb = g_cb;
776- if ((g_cb->pos - g_cb->nv) + n <= g_cb->size)
777- break;
778- g_cb = g_cb->next;
779- }
780-
781- if (!g_cb) {
782- size = (n <= MINNVBLOCK) ? MINNVBLOCK : n;
783- g_cb = xzalloc(sizeof(nvblock) + size * sizeof(var));
784- g_cb->size = size;
785- g_cb->pos = g_cb->nv;
786- g_cb->prev = pb;
787- /*g_cb->next = NULL; - xzalloc did it */
788- if (pb)
789- pb->next = g_cb;
790- }
791-
792- v = r = g_cb->pos;
793- g_cb->pos += n;
794-
795- while (v < g_cb->pos) {
796- v->type = 0;
797- v->string = NULL;
798- v++;
799- }
800-
801- return r;
802-}
803-
804-static void nvfree(var *v)
805-{
806- var *p;
807-
808- if (v < g_cb->nv || v >= g_cb->pos)
809- syntax_error(EMSG_INTERNAL_ERROR);
810-
811- for (p = v; p < g_cb->pos; p++) {
812- if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) {
813- clear_array(iamarray(p));
814- free(p->x.array->items);
815- free(p->x.array);
816- }
817- if (p->type & VF_WALK) {
818- walker_list *n;
819- walker_list *w = p->x.walker;
820- debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker);
821- p->x.walker = NULL;
822- while (w) {
823- n = w->prev;
824- debug_printf_walker(" free(%p)\n", w);
825- free(w);
826- w = n;
827- }
828- }
829- clrvar(p);
830- }
831-
832- g_cb->pos = v;
833- while (g_cb->prev && g_cb->pos == g_cb->nv) {
834- g_cb = g_cb->prev;
835- }
836-}
837-
838 /* ------- awk program text parsing ------- */
839
840-/* Parse next token pointed by global pos, place results into global ttt.
841- * If token isn't expected, give away. Return token class
842+/* Parse next token pointed by global pos, place results into global t_XYZ variables.
843+ * If token isn't expected, print error message and die.
844+ * Return token class (also store it in t_tclass).
845 */
846 static uint32_t next_token(uint32_t expected)
847 {
848-#define concat_inserted (G.next_token__concat_inserted)
849-#define save_tclass (G.next_token__save_tclass)
850-#define save_info (G.next_token__save_info)
851-/* Initialized to TC_OPTERM: */
852-#define ltclass (G.next_token__ltclass)
853+#define concat_inserted (G1.next_token__concat_inserted)
854+#define save_tclass (G1.next_token__save_tclass)
855+#define save_info (G1.next_token__save_info)
856
857- char *p, *s;
858+ char *p;
859 const char *tl;
860- uint32_t tc;
861 const uint32_t *ti;
862+ uint32_t tc, last_token_class;
863+
864+ last_token_class = t_tclass; /* t_tclass is initialized to TC_NEWLINE */
865+
866+ debug_printf_parse("%s() expected(%x):", __func__, expected);
867+ debug_parse_print_tc(expected);
868+ debug_printf_parse("\n");
869
870 if (t_rollback) {
871 debug_printf_parse("%s: using rolled-back token\n", __func__);
872@@ -1080,6 +1111,10 @@ static uint32_t next_token(uint32_t expected)
873 t_info = save_info;
874 } else {
875 p = g_pos;
876+ if (g_saved_ch != '\0') {
877+ *p = g_saved_ch;
878+ g_saved_ch = '\0';
879+ }
880 readnext:
881 p = skip_spaces(p);
882 g_lineno = t_lineno;
883@@ -1087,15 +1122,12 @@ static uint32_t next_token(uint32_t expected)
884 while (*p != '\n' && *p != '\0')
885 p++;
886
887- if (*p == '\n')
888- t_lineno++;
889-
890 if (*p == '\0') {
891 tc = TC_EOF;
892 debug_printf_parse("%s: token found: TC_EOF\n", __func__);
893 } else if (*p == '\"') {
894 /* it's a string */
895- t_string = s = ++p;
896+ char *s = t_string = ++p;
897 while (*p != '\"') {
898 char *pp;
899 if (*p == '\0' || *p == '\n')
900@@ -1110,7 +1142,7 @@ static uint32_t next_token(uint32_t expected)
901 debug_printf_parse("%s: token found:'%s' TC_STRING\n", __func__, t_string);
902 } else if ((expected & TC_REGEXP) && *p == '/') {
903 /* it's regexp */
904- t_string = s = ++p;
905+ char *s = t_string = ++p;
906 while (*p != '/') {
907 if (*p == '\0' || *p == '\n')
908 syntax_error(EMSG_UNEXP_EOS);
909@@ -1141,6 +1173,11 @@ static uint32_t next_token(uint32_t expected)
910 tc = TC_NUMBER;
911 debug_printf_parse("%s: token found:%f TC_NUMBER\n", __func__, t_double);
912 } else {
913+ char *end_of_name;
914+
915+ if (*p == '\n')
916+ t_lineno++;
917+
918 /* search for something known */
919 tl = tokenlist;
920 tc = 0x00000001;
921@@ -1155,9 +1192,9 @@ static uint32_t next_token(uint32_t expected)
922 * token matches,
923 * and it's not a longer word,
924 */
925- if ((tc & (expected | TC_WORD | TC_NEWLINE))
926+ if ((tc & (expected | TS_WORD | TC_NEWLINE))
927 && strncmp(p, tl, l) == 0
928- && !((tc & TC_WORD) && isalnum_(p[l]))
929+ && !((tc & TS_WORD) && isalnum_(p[l]))
930 ) {
931 /* then this is what we are looking for */
932 t_info = *ti;
933@@ -1174,67 +1211,94 @@ static uint32_t next_token(uint32_t expected)
934 if (!isalnum_(*p))
935 syntax_error(EMSG_UNEXP_TOKEN); /* no */
936 /* yes */
937- t_string = --p;
938- while (isalnum_(*++p)) {
939- p[-1] = *p;
940- }
941- p[-1] = '\0';
942- tc = TC_VARIABLE;
943- /* also consume whitespace between functionname and bracket */
944- if (!(expected & TC_VARIABLE) || (expected & TC_ARRAY))
945+ t_string = p;
946+ while (isalnum_(*p))
947+ p++;
948+ end_of_name = p;
949+
950+ if (last_token_class == TC_FUNCDECL)
951+ /* eat space in "function FUNC (...) {...}" declaration */
952 p = skip_spaces(p);
953+ else if (expected & TC_ARRAY) {
954+ /* eat space between array name and [ */
955+ char *s = skip_spaces(p);
956+ if (*s == '[') /* array ref, not just a name? */
957+ p = s;
958+ }
959+ /* else: do NOT consume whitespace after variable name!
960+ * gawk allows definition "function FUNC (p) {...}" - note space,
961+ * but disallows the call "FUNC (p)" because it isn't one -
962+ * expression "v (a)" should NOT be parsed as TC_FUNCTION:
963+ * it is a valid concatenation if "v" is a variable,
964+ * not a function name (and type of name is not known at parse time).
965+ */
966+
967 if (*p == '(') {
968+ p++;
969 tc = TC_FUNCTION;
970 debug_printf_parse("%s: token found:'%s' TC_FUNCTION\n", __func__, t_string);
971+ } else if (*p == '[') {
972+ p++;
973+ tc = TC_ARRAY;
974+ debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string);
975 } else {
976- if (*p == '[') {
977- p++;
978- tc = TC_ARRAY;
979- debug_printf_parse("%s: token found:'%s' TC_ARRAY\n", __func__, t_string);
980- } else
981- debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string);
982+ tc = TC_VARIABLE;
983+ debug_printf_parse("%s: token found:'%s' TC_VARIABLE\n", __func__, t_string);
984+ if (end_of_name == p) {
985+ /* there is no space for trailing NUL in t_string!
986+ * We need to save the char we are going to NUL.
987+ * (we'll use it in future call to next_token())
988+ */
989+ g_saved_ch = *end_of_name;
990+// especially pathological example is V="abc"; V.2 - it's V concatenated to .2
991+// (it evaluates to "abc0.2"). Because of this case, we can't simply cache
992+// '.' and analyze it later: we also have to *store it back* in next
993+// next_token(), in order to give my_strtod() the undamaged ".2" string.
994+ }
995 }
996+ *end_of_name = '\0'; /* terminate t_string */
997 }
998 token_found:
999 g_pos = p;
1000
1001 /* skipping newlines in some cases */
1002- if ((ltclass & TC_NOTERM) && (tc & TC_NEWLINE))
1003+ if ((last_token_class & TS_NOTERM) && (tc & TC_NEWLINE))
1004 goto readnext;
1005
1006 /* insert concatenation operator when needed */
1007- debug_printf_parse("%s: %x %x %x concat_inserted?\n", __func__,
1008- (ltclass & TC_CONCAT1), (tc & TC_CONCAT2), (expected & TC_BINOP));
1009- if ((ltclass & TC_CONCAT1) && (tc & TC_CONCAT2) && (expected & TC_BINOP)
1010- && !(ltclass == TC_LENGTH && tc == TC_SEQSTART) /* but not for "length(..." */
1011+ debug_printf_parse("%s: concat_inserted if all nonzero: %x %x %x %x\n", __func__,
1012+ (last_token_class & TS_CONCAT_L), (tc & TS_CONCAT_R), (expected & TS_BINOP),
1013+ !(last_token_class == TC_LENGTH && tc == TC_LPAREN));
1014+ if ((last_token_class & TS_CONCAT_L) && (tc & TS_CONCAT_R) && (expected & TS_BINOP)
1015+ && !(last_token_class == TC_LENGTH && tc == TC_LPAREN) /* but not for "length(..." */
1016 ) {
1017 concat_inserted = TRUE;
1018 save_tclass = tc;
1019 save_info = t_info;
1020- tc = TC_BINOP;
1021+ tc = TC_BINOPX;
1022 t_info = OC_CONCAT | SS | P(35);
1023 }
1024
1025- debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, t_tclass);
1026 t_tclass = tc;
1027+ debug_printf_parse("%s: t_tclass=tc=%x\n", __func__, tc);
1028 }
1029- ltclass = t_tclass;
1030-
1031 /* Are we ready for this? */
1032- if (!(ltclass & expected)) {
1033- syntax_error((ltclass & (TC_NEWLINE | TC_EOF)) ?
1034+ if (!(t_tclass & expected)) {
1035+ syntax_error((last_token_class & (TC_NEWLINE | TC_EOF)) ?
1036 EMSG_UNEXP_EOS : EMSG_UNEXP_TOKEN);
1037 }
1038
1039- debug_printf_parse("%s: returning, ltclass:%x t_double:%f\n", __func__, ltclass, t_double);
1040- return ltclass;
1041+ debug_printf_parse("%s: returning, t_double:%f t_tclass:", __func__, t_double);
1042+ debug_parse_print_tc(t_tclass);
1043+ debug_printf_parse("\n");
1044+
1045+ return t_tclass;
1046 #undef concat_inserted
1047 #undef save_tclass
1048 #undef save_info
1049-#undef ltclass
1050 }
1051
1052-static void rollback_token(void)
1053+static ALWAYS_INLINE void rollback_token(void)
1054 {
1055 t_rollback = TRUE;
1056 }
1057@@ -1251,169 +1315,188 @@ static node *new_node(uint32_t info)
1058
1059 static void mk_re_node(const char *s, node *n, regex_t *re)
1060 {
1061- n->info = OC_REGEXP;
1062+ n->info = TI_REGEXP;
1063 n->l.re = re;
1064 n->r.ire = re + 1;
1065 xregcomp(re, s, REG_EXTENDED);
1066 xregcomp(re + 1, s, REG_EXTENDED | REG_ICASE);
1067 }
1068
1069-static node *condition(void)
1070+static node *parse_expr(uint32_t);
1071+
1072+static node *parse_lrparen_list(void)
1073 {
1074- next_token(TC_SEQSTART);
1075- return parse_expr(TC_SEQTERM);
1076+ next_token(TC_LPAREN);
1077+ return parse_expr(TC_RPAREN);
1078 }
1079
1080 /* parse expression terminated by given argument, return ptr
1081 * to built subtree. Terminator is eaten by parse_expr */
1082-static node *parse_expr(uint32_t iexp)
1083+static node *parse_expr(uint32_t term_tc)
1084 {
1085 node sn;
1086 node *cn = &sn;
1087 node *vn, *glptr;
1088- uint32_t tc, xtc;
1089+ uint32_t tc, expected_tc;
1090 var *v;
1091
1092- debug_printf_parse("%s(%x)\n", __func__, iexp);
1093+ debug_printf_parse("%s() term_tc(%x):", __func__, term_tc);
1094+ debug_parse_print_tc(term_tc);
1095+ debug_printf_parse("\n");
1096
1097 sn.info = PRIMASK;
1098 sn.r.n = sn.a.n = glptr = NULL;
1099- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP | iexp;
1100+ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP | term_tc;
1101
1102- while (!((tc = next_token(xtc)) & iexp)) {
1103+ while (!((tc = next_token(expected_tc)) & term_tc)) {
1104
1105- if (glptr && (t_info == (OC_COMPARE | VV | P(39) | 2))) {
1106+ if (glptr && (t_info == TI_LESS)) {
1107 /* input redirection (<) attached to glptr node */
1108 debug_printf_parse("%s: input redir\n", __func__);
1109 cn = glptr->l.n = new_node(OC_CONCAT | SS | P(37));
1110 cn->a.n = glptr;
1111- xtc = TC_OPERAND | TC_UOPPRE;
1112+ expected_tc = TS_OPERAND | TS_UOPPRE;
1113 glptr = NULL;
1114-
1115- } else if (tc & (TC_BINOP | TC_UOPPOST)) {
1116- debug_printf_parse("%s: TC_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
1117+ continue;
1118+ }
1119+ if (tc & (TS_BINOP | TC_UOPPOST)) {
1120+ debug_printf_parse("%s: TS_BINOP | TC_UOPPOST tc:%x\n", __func__, tc);
1121 /* for binary and postfix-unary operators, jump back over
1122 * previous operators with higher priority */
1123 vn = cn;
1124 while (((t_info & PRIMASK) > (vn->a.n->info & PRIMASK2))
1125- || ((t_info == vn->info) && ((t_info & OPCLSMASK) == OC_COLON))
1126+ || ((t_info == vn->info) && t_info == TI_COLON)
1127 ) {
1128 vn = vn->a.n;
1129 if (!vn->a.n) syntax_error(EMSG_UNEXP_TOKEN);
1130 }
1131- if ((t_info & OPCLSMASK) == OC_TERNARY)
1132+ if (t_info == TI_TERNARY)
1133+//TODO: why?
1134 t_info += P(6);
1135 cn = vn->a.n->r.n = new_node(t_info);
1136 cn->a.n = vn->a.n;
1137- if (tc & TC_BINOP) {
1138+ if (tc & TS_BINOP) {
1139 cn->l.n = vn;
1140- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
1141- if ((t_info & OPCLSMASK) == OC_PGETLINE) {
1142+//FIXME: this is the place to detect and reject assignments to non-lvalues.
1143+//Currently we allow "assignments" to consts and temporaries, nonsense like this:
1144+// awk 'BEGIN { "qwe" = 1 }'
1145+// awk 'BEGIN { 7 *= 7 }'
1146+// awk 'BEGIN { length("qwe") = 1 }'
1147+// awk 'BEGIN { (1+1) += 3 }'
1148+ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP;
1149+ if (t_info == TI_PGETLINE) {
1150 /* it's a pipe */
1151 next_token(TC_GETLINE);
1152 /* give maximum priority to this pipe */
1153 cn->info &= ~PRIMASK;
1154- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1155+ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc;
1156 }
1157 } else {
1158 cn->r.n = vn;
1159- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1160+ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc;
1161 }
1162 vn->a.n = cn;
1163+ continue;
1164+ }
1165
1166- } else {
1167- debug_printf_parse("%s: other\n", __func__);
1168- /* for operands and prefix-unary operators, attach them
1169- * to last node */
1170- vn = cn;
1171- cn = vn->r.n = new_node(t_info);
1172- cn->a.n = vn;
1173- xtc = TC_OPERAND | TC_UOPPRE | TC_REGEXP;
1174- if (tc & (TC_OPERAND | TC_REGEXP)) {
1175- debug_printf_parse("%s: TC_OPERAND | TC_REGEXP\n", __func__);
1176- xtc = TC_UOPPRE | TC_UOPPOST | TC_BINOP | TC_OPERAND | iexp;
1177- /* one should be very careful with switch on tclass -
1178- * only simple tclasses should be used! */
1179- switch (tc) {
1180- case TC_VARIABLE:
1181- case TC_ARRAY:
1182- debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
1183- cn->info = OC_VAR;
1184- v = hash_search(ahash, t_string);
1185- if (v != NULL) {
1186- cn->info = OC_FNARG;
1187- cn->l.aidx = v->x.aidx;
1188- } else {
1189- cn->l.v = newvar(t_string);
1190- }
1191- if (tc & TC_ARRAY) {
1192- cn->info |= xS;
1193- cn->r.n = parse_expr(TC_ARRTERM);
1194- }
1195- break;
1196+ debug_printf_parse("%s: other, t_info:%x\n", __func__, t_info);
1197+ /* for operands and prefix-unary operators, attach them
1198+ * to last node */
1199+ vn = cn;
1200+ cn = vn->r.n = new_node(t_info);
1201+ cn->a.n = vn;
1202
1203- case TC_NUMBER:
1204- case TC_STRING:
1205- debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
1206- cn->info = OC_VAR;
1207- v = cn->l.v = xzalloc(sizeof(var));
1208- if (tc & TC_NUMBER)
1209- setvar_i(v, t_double);
1210- else {
1211- setvar_s(v, t_string);
1212- xtc &= ~TC_UOPPOST; /* "str"++ is not allowed */
1213- }
1214- break;
1215+ expected_tc = TS_OPERAND | TS_UOPPRE | TC_REGEXP;
1216+ if (t_info == TI_PREINC || t_info == TI_PREDEC)
1217+ expected_tc = TS_LVALUE | TC_UOPPRE1;
1218
1219- case TC_REGEXP:
1220- debug_printf_parse("%s: TC_REGEXP\n", __func__);
1221- mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
1222- break;
1223+ if (!(tc & (TS_OPERAND | TC_REGEXP)))
1224+ continue;
1225
1226- case TC_FUNCTION:
1227- debug_printf_parse("%s: TC_FUNCTION\n", __func__);
1228- cn->info = OC_FUNC;
1229- cn->r.f = newfunc(t_string);
1230- cn->l.n = condition();
1231- break;
1232+ debug_printf_parse("%s: TS_OPERAND | TC_REGEXP\n", __func__);
1233+ expected_tc = TS_UOPPRE | TC_UOPPOST | TS_BINOP | TS_OPERAND | term_tc;
1234+ /* one should be very careful with switch on tclass -
1235+ * only simple tclasses should be used (TC_xyz, not TS_xyz) */
1236+ switch (tc) {
1237+ case TC_VARIABLE:
1238+ case TC_ARRAY:
1239+ debug_printf_parse("%s: TC_VARIABLE | TC_ARRAY\n", __func__);
1240+ cn->info = OC_VAR;
1241+ v = hash_search(ahash, t_string);
1242+ if (v != NULL) {
1243+ cn->info = OC_FNARG;
1244+ cn->l.aidx = v->x.aidx;
1245+ } else {
1246+ cn->l.v = newvar(t_string);
1247+ }
1248+ if (tc & TC_ARRAY) {
1249+ cn->info |= xS;
1250+ cn->r.n = parse_expr(TC_ARRTERM);
1251+ }
1252+ break;
1253
1254- case TC_SEQSTART:
1255- debug_printf_parse("%s: TC_SEQSTART\n", __func__);
1256- cn = vn->r.n = parse_expr(TC_SEQTERM);
1257- if (!cn)
1258- syntax_error("Empty sequence");
1259- cn->a.n = vn;
1260- break;
1261+ case TC_NUMBER:
1262+ case TC_STRING:
1263+ debug_printf_parse("%s: TC_NUMBER | TC_STRING\n", __func__);
1264+ cn->info = OC_VAR;
1265+ v = cn->l.v = xzalloc(sizeof(var));
1266+ if (tc & TC_NUMBER)
1267+ setvar_i(v, t_double);
1268+ else {
1269+ setvar_s(v, t_string);
1270+ expected_tc &= ~TC_UOPPOST; /* "str"++ is not allowed */
1271+ }
1272+ break;
1273
1274- case TC_GETLINE:
1275- debug_printf_parse("%s: TC_GETLINE\n", __func__);
1276- glptr = cn;
1277- xtc = TC_OPERAND | TC_UOPPRE | TC_BINOP | iexp;
1278- break;
1279+ case TC_REGEXP:
1280+ debug_printf_parse("%s: TC_REGEXP\n", __func__);
1281+ mk_re_node(t_string, cn, xzalloc(sizeof(regex_t)*2));
1282+ break;
1283
1284- case TC_BUILTIN:
1285- debug_printf_parse("%s: TC_BUILTIN\n", __func__);
1286- cn->l.n = condition();
1287- break;
1288+ case TC_FUNCTION:
1289+ debug_printf_parse("%s: TC_FUNCTION\n", __func__);
1290+ cn->info = OC_FUNC;
1291+ cn->r.f = newfunc(t_string);
1292+ cn->l.n = parse_expr(TC_RPAREN);
1293+ break;
1294
1295- case TC_LENGTH:
1296- debug_printf_parse("%s: TC_LENGTH\n", __func__);
1297- next_token(TC_SEQSTART /* length(...) */
1298- | TC_OPTERM /* length; (or newline)*/
1299- | TC_GRPTERM /* length } */
1300- | TC_BINOPX /* length <op> NUM */
1301- | TC_COMMA /* print length, 1 */
1302- );
1303- rollback_token();
1304- if (t_tclass & TC_SEQSTART) {
1305- /* It was a "(" token. Handle just like TC_BUILTIN */
1306- cn->l.n = condition();
1307- }
1308- break;
1309- }
1310+ case TC_LPAREN:
1311+ debug_printf_parse("%s: TC_LPAREN\n", __func__);
1312+ cn = vn->r.n = parse_expr(TC_RPAREN);
1313+ if (!cn)
1314+ syntax_error("Empty sequence");
1315+ cn->a.n = vn;
1316+ break;
1317+
1318+ case TC_GETLINE:
1319+ debug_printf_parse("%s: TC_GETLINE\n", __func__);
1320+ glptr = cn;
1321+ expected_tc = TS_OPERAND | TS_UOPPRE | TS_BINOP | term_tc;
1322+ break;
1323+
1324+ case TC_BUILTIN:
1325+ debug_printf_parse("%s: TC_BUILTIN\n", __func__);
1326+ cn->l.n = parse_lrparen_list();
1327+ break;
1328+
1329+ case TC_LENGTH:
1330+ debug_printf_parse("%s: TC_LENGTH\n", __func__);
1331+ tc = next_token(TC_LPAREN /* length(...) */
1332+ | TC_SEMICOL /* length; */
1333+ | TC_NEWLINE /* length<newline> */
1334+ | TC_RBRACE /* length } */
1335+ | TC_BINOPX /* length <op> NUM */
1336+ | TC_COMMA /* print length, 1 */
1337+ );
1338+ if (tc != TC_LPAREN)
1339+ rollback_token();
1340+ else {
1341+ /* It was a "(" token. Handle just like TC_BUILTIN */
1342+ cn->l.n = parse_expr(TC_RPAREN);
1343 }
1344+ break;
1345 }
1346- }
1347+ } /* while() */
1348
1349 debug_printf_parse("%s() returns %p\n", __func__, sn.r.n);
1350 return sn.r.n;
1351@@ -1430,7 +1513,7 @@ static node *chain_node(uint32_t info)
1352 if (seq->programname != g_progname) {
1353 seq->programname = g_progname;
1354 n = chain_node(OC_NEWSOURCE);
1355- n->l.new_progname = xstrdup(g_progname);
1356+ n->l.new_progname = g_progname;
1357 }
1358
1359 n = seq->last;
1360@@ -1446,14 +1529,16 @@ static void chain_expr(uint32_t info)
1361
1362 n = chain_node(info);
1363
1364- n->l.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1365+ n->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_RBRACE);
1366 if ((info & OF_REQUIRED) && !n->l.n)
1367 syntax_error(EMSG_TOO_FEW_ARGS);
1368
1369- if (t_tclass & TC_GRPTERM)
1370+ if (t_tclass & TC_RBRACE)
1371 rollback_token();
1372 }
1373
1374+static void chain_group(void);
1375+
1376 static node *chain_loop(node *nn)
1377 {
1378 node *n, *n2, *save_brk, *save_cont;
1379@@ -1477,207 +1562,284 @@ static node *chain_loop(node *nn)
1380 return n;
1381 }
1382
1383+static void chain_until_rbrace(void)
1384+{
1385+ uint32_t tc;
1386+ while ((tc = next_token(TS_GRPSEQ | TC_RBRACE)) != TC_RBRACE) {
1387+ debug_printf_parse("%s: !TC_RBRACE\n", __func__);
1388+ if (tc == TC_NEWLINE)
1389+ continue;
1390+ rollback_token();
1391+ chain_group();
1392+ }
1393+ debug_printf_parse("%s: TC_RBRACE\n", __func__);
1394+}
1395+
1396 /* parse group and attach it to chain */
1397 static void chain_group(void)
1398 {
1399- uint32_t c;
1400+ uint32_t tc;
1401 node *n, *n2, *n3;
1402
1403 do {
1404- c = next_token(TC_GRPSEQ);
1405- } while (c & TC_NEWLINE);
1406-
1407- if (c & TC_GRPSTART) {
1408- debug_printf_parse("%s: TC_GRPSTART\n", __func__);
1409- while (next_token(TC_GRPSEQ | TC_GRPTERM) != TC_GRPTERM) {
1410- debug_printf_parse("%s: !TC_GRPTERM\n", __func__);
1411- if (t_tclass & TC_NEWLINE)
1412- continue;
1413- rollback_token();
1414- chain_group();
1415- }
1416- debug_printf_parse("%s: TC_GRPTERM\n", __func__);
1417- } else if (c & (TC_OPSEQ | TC_OPTERM)) {
1418- debug_printf_parse("%s: TC_OPSEQ | TC_OPTERM\n", __func__);
1419+ tc = next_token(TS_GRPSEQ);
1420+ } while (tc == TC_NEWLINE);
1421+
1422+ if (tc == TC_LBRACE) {
1423+ debug_printf_parse("%s: TC_LBRACE\n", __func__);
1424+ chain_until_rbrace();
1425+ return;
1426+ }
1427+ if (tc & (TS_OPSEQ | TC_SEMICOL)) {
1428+ debug_printf_parse("%s: TS_OPSEQ | TC_SEMICOL\n", __func__);
1429 rollback_token();
1430 chain_expr(OC_EXEC | Vx);
1431- } else {
1432- /* TC_STATEMNT */
1433- debug_printf_parse("%s: TC_STATEMNT(?)\n", __func__);
1434- switch (t_info & OPCLSMASK) {
1435- case ST_IF:
1436- debug_printf_parse("%s: ST_IF\n", __func__);
1437- n = chain_node(OC_BR | Vx);
1438- n->l.n = condition();
1439+ return;
1440+ }
1441+
1442+ /* TS_STATEMNT */
1443+ debug_printf_parse("%s: TS_STATEMNT(?)\n", __func__);
1444+ switch (t_info & OPCLSMASK) {
1445+ case ST_IF:
1446+ debug_printf_parse("%s: ST_IF\n", __func__);
1447+ n = chain_node(OC_BR | Vx);
1448+ n->l.n = parse_lrparen_list();
1449+ chain_group();
1450+ n2 = chain_node(OC_EXEC);
1451+ n->r.n = seq->last;
1452+ if (next_token(TS_GRPSEQ | TC_RBRACE | TC_ELSE) == TC_ELSE) {
1453 chain_group();
1454- n2 = chain_node(OC_EXEC);
1455- n->r.n = seq->last;
1456- if (next_token(TC_GRPSEQ | TC_GRPTERM | TC_ELSE) == TC_ELSE) {
1457- chain_group();
1458- n2->a.n = seq->last;
1459- } else {
1460- rollback_token();
1461- }
1462- break;
1463+ n2->a.n = seq->last;
1464+ } else {
1465+ rollback_token();
1466+ }
1467+ break;
1468
1469- case ST_WHILE:
1470- debug_printf_parse("%s: ST_WHILE\n", __func__);
1471- n2 = condition();
1472- n = chain_loop(NULL);
1473- n->l.n = n2;
1474- break;
1475+ case ST_WHILE:
1476+ debug_printf_parse("%s: ST_WHILE\n", __func__);
1477+ n2 = parse_lrparen_list();
1478+ n = chain_loop(NULL);
1479+ n->l.n = n2;
1480+ break;
1481
1482- case ST_DO:
1483- debug_printf_parse("%s: ST_DO\n", __func__);
1484- n2 = chain_node(OC_EXEC);
1485- n = chain_loop(NULL);
1486- n2->a.n = n->a.n;
1487- next_token(TC_WHILE);
1488- n->l.n = condition();
1489- break;
1490+ case ST_DO:
1491+ debug_printf_parse("%s: ST_DO\n", __func__);
1492+ n2 = chain_node(OC_EXEC);
1493+ n = chain_loop(NULL);
1494+ n2->a.n = n->a.n;
1495+ next_token(TC_WHILE);
1496+ n->l.n = parse_lrparen_list();
1497+ break;
1498
1499- case ST_FOR:
1500- debug_printf_parse("%s: ST_FOR\n", __func__);
1501- next_token(TC_SEQSTART);
1502- n2 = parse_expr(TC_SEMICOL | TC_SEQTERM);
1503- if (t_tclass & TC_SEQTERM) { /* for-in */
1504- if (!n2 || (n2->info & OPCLSMASK) != OC_IN)
1505- syntax_error(EMSG_UNEXP_TOKEN);
1506- n = chain_node(OC_WALKINIT | VV);
1507- n->l.n = n2->l.n;
1508- n->r.n = n2->r.n;
1509- n = chain_loop(NULL);
1510- n->info = OC_WALKNEXT | Vx;
1511- n->l.n = n2->l.n;
1512- } else { /* for (;;) */
1513- n = chain_node(OC_EXEC | Vx);
1514- n->l.n = n2;
1515- n2 = parse_expr(TC_SEMICOL);
1516- n3 = parse_expr(TC_SEQTERM);
1517- n = chain_loop(n3);
1518- n->l.n = n2;
1519- if (!n2)
1520- n->info = OC_EXEC;
1521- }
1522- break;
1523+ case ST_FOR:
1524+ debug_printf_parse("%s: ST_FOR\n", __func__);
1525+ next_token(TC_LPAREN);
1526+ n2 = parse_expr(TC_SEMICOL | TC_RPAREN);
1527+ if (t_tclass & TC_RPAREN) { /* for (I in ARRAY) */
1528+ if (!n2 || n2->info != TI_IN)
1529+ syntax_error(EMSG_UNEXP_TOKEN);
1530+ n = chain_node(OC_WALKINIT | VV);
1531+ n->l.n = n2->l.n;
1532+ n->r.n = n2->r.n;
1533+ n = chain_loop(NULL);
1534+ n->info = OC_WALKNEXT | Vx;
1535+ n->l.n = n2->l.n;
1536+ } else { /* for (;;) */
1537+ n = chain_node(OC_EXEC | Vx);
1538+ n->l.n = n2;
1539+ n2 = parse_expr(TC_SEMICOL);
1540+ n3 = parse_expr(TC_RPAREN);
1541+ n = chain_loop(n3);
1542+ n->l.n = n2;
1543+ if (!n2)
1544+ n->info = OC_EXEC;
1545+ }
1546+ break;
1547
1548- case OC_PRINT:
1549- case OC_PRINTF:
1550- debug_printf_parse("%s: OC_PRINT[F]\n", __func__);
1551- n = chain_node(t_info);
1552- n->l.n = parse_expr(TC_OPTERM | TC_OUTRDR | TC_GRPTERM);
1553- if (t_tclass & TC_OUTRDR) {
1554- n->info |= t_info;
1555- n->r.n = parse_expr(TC_OPTERM | TC_GRPTERM);
1556- }
1557- if (t_tclass & TC_GRPTERM)
1558- rollback_token();
1559- break;
1560+ case OC_PRINT:
1561+ case OC_PRINTF:
1562+ debug_printf_parse("%s: OC_PRINT[F]\n", __func__);
1563+ n = chain_node(t_info);
1564+ n->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_OUTRDR | TC_RBRACE);
1565+ if (t_tclass & TC_OUTRDR) {
1566+ n->info |= t_info;
1567+ n->r.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_RBRACE);
1568+ }
1569+ if (t_tclass & TC_RBRACE)
1570+ rollback_token();
1571+ break;
1572
1573- case OC_BREAK:
1574- debug_printf_parse("%s: OC_BREAK\n", __func__);
1575- n = chain_node(OC_EXEC);
1576- n->a.n = break_ptr;
1577- chain_expr(t_info);
1578- break;
1579+ case OC_BREAK:
1580+ debug_printf_parse("%s: OC_BREAK\n", __func__);
1581+ n = chain_node(OC_EXEC);
1582+ if (!break_ptr)
1583+ syntax_error("'break' not in a loop");
1584+ n->a.n = break_ptr;
1585+ chain_expr(t_info);
1586+ break;
1587
1588- case OC_CONTINUE:
1589- debug_printf_parse("%s: OC_CONTINUE\n", __func__);
1590- n = chain_node(OC_EXEC);
1591- n->a.n = continue_ptr;
1592- chain_expr(t_info);
1593- break;
1594+ case OC_CONTINUE:
1595+ debug_printf_parse("%s: OC_CONTINUE\n", __func__);
1596+ n = chain_node(OC_EXEC);
1597+ if (!continue_ptr)
1598+ syntax_error("'continue' not in a loop");
1599+ n->a.n = continue_ptr;
1600+ chain_expr(t_info);
1601+ break;
1602
1603- /* delete, next, nextfile, return, exit */
1604- default:
1605- debug_printf_parse("%s: default\n", __func__);
1606- chain_expr(t_info);
1607- }
1608+ /* delete, next, nextfile, return, exit */
1609+ default:
1610+ debug_printf_parse("%s: default\n", __func__);
1611+ chain_expr(t_info);
1612 }
1613 }
1614
1615 static void parse_program(char *p)
1616 {
1617- uint32_t tclass;
1618- node *cn;
1619- func *f;
1620- var *v;
1621+ debug_printf_parse("%s()\n", __func__);
1622
1623 g_pos = p;
1624 t_lineno = 1;
1625- while ((tclass = next_token(TC_EOF | TC_OPSEQ | TC_GRPSTART |
1626- TC_OPTERM | TC_BEGIN | TC_END | TC_FUNCDECL)) != TC_EOF) {
1627+ for (;;) {
1628+ uint32_t tclass;
1629
1630- if (tclass & TC_OPTERM) {
1631- debug_printf_parse("%s: TC_OPTERM\n", __func__);
1632+ tclass = next_token(TS_OPSEQ | TC_LBRACE | TC_BEGIN | TC_END | TC_FUNCDECL
1633+ | TC_EOF | TC_NEWLINE /* but not TC_SEMICOL */);
1634+ got_tok:
1635+ if (tclass == TC_EOF) {
1636+ debug_printf_parse("%s: TC_EOF\n", __func__);
1637+ break;
1638+ }
1639+ if (tclass == TC_NEWLINE) {
1640+ debug_printf_parse("%s: TC_NEWLINE\n", __func__);
1641 continue;
1642 }
1643-
1644- seq = &mainseq;
1645- if (tclass & TC_BEGIN) {
1646+ if (tclass == TC_BEGIN) {
1647 debug_printf_parse("%s: TC_BEGIN\n", __func__);
1648 seq = &beginseq;
1649- chain_group();
1650- } else if (tclass & TC_END) {
1651+ /* ensure there is no newline between BEGIN and { */
1652+ next_token(TC_LBRACE);
1653+ chain_until_rbrace();
1654+ goto next_tok;
1655+ }
1656+ if (tclass == TC_END) {
1657 debug_printf_parse("%s: TC_END\n", __func__);
1658 seq = &endseq;
1659- chain_group();
1660- } else if (tclass & TC_FUNCDECL) {
1661+ /* ensure there is no newline between END and { */
1662+ next_token(TC_LBRACE);
1663+ chain_until_rbrace();
1664+ goto next_tok;
1665+ }
1666+ if (tclass == TC_FUNCDECL) {
1667+ func *f;
1668+
1669 debug_printf_parse("%s: TC_FUNCDECL\n", __func__);
1670 next_token(TC_FUNCTION);
1671- g_pos++;
1672 f = newfunc(t_string);
1673- f->body.first = NULL;
1674- f->nargs = 0;
1675- /* Match func arg list: a comma sep list of >= 0 args, and a close paren */
1676- while (next_token(TC_VARIABLE | TC_SEQTERM | TC_COMMA)) {
1677- /* Either an empty arg list, or trailing comma from prev iter
1678- * must be followed by an arg */
1679- if (f->nargs == 0 && t_tclass == TC_SEQTERM)
1680- break;
1681-
1682- /* TC_SEQSTART/TC_COMMA must be followed by TC_VARIABLE */
1683- if (t_tclass != TC_VARIABLE)
1684+ if (f->defined)
1685+ syntax_error("Duplicate function");
1686+ f->defined = 1;
1687+ //f->body.first = NULL; - already is
1688+ //f->nargs = 0; - already is
1689+ /* func arg list: comma sep list of args, and a close paren */
1690+ for (;;) {
1691+ var *v;
1692+ if (next_token(TC_VARIABLE | TC_RPAREN) == TC_RPAREN) {
1693+ if (f->nargs == 0)
1694+ break; /* func() is ok */
1695+ /* func(a,) is not ok */
1696 syntax_error(EMSG_UNEXP_TOKEN);
1697-
1698+ }
1699 v = findvar(ahash, t_string);
1700 v->x.aidx = f->nargs++;
1701-
1702 /* Arg followed either by end of arg list or 1 comma */
1703- if (next_token(TC_COMMA | TC_SEQTERM) & TC_SEQTERM)
1704+ if (next_token(TC_COMMA | TC_RPAREN) == TC_RPAREN)
1705 break;
1706- if (t_tclass != TC_COMMA)
1707- syntax_error(EMSG_UNEXP_TOKEN);
1708+ /* it was a comma, we ate it */
1709 }
1710 seq = &f->body;
1711- chain_group();
1712- clear_array(ahash);
1713- } else if (tclass & TC_OPSEQ) {
1714- debug_printf_parse("%s: TC_OPSEQ\n", __func__);
1715+ /* ensure there is { after "func F(...)" - but newlines are allowed */
1716+ while (next_token(TC_LBRACE | TC_NEWLINE) == TC_NEWLINE)
1717+ continue;
1718+ chain_until_rbrace();
1719+ hash_clear(ahash);
1720+ goto next_tok;
1721+ }
1722+ seq = &mainseq;
1723+ if (tclass & TS_OPSEQ) {
1724+ node *cn;
1725+
1726+ debug_printf_parse("%s: TS_OPSEQ\n", __func__);
1727 rollback_token();
1728 cn = chain_node(OC_TEST);
1729- cn->l.n = parse_expr(TC_OPTERM | TC_EOF | TC_GRPSTART);
1730- if (t_tclass & TC_GRPSTART) {
1731- debug_printf_parse("%s: TC_GRPSTART\n", __func__);
1732- rollback_token();
1733- chain_group();
1734+ cn->l.n = parse_expr(TC_SEMICOL | TC_NEWLINE | TC_EOF | TC_LBRACE);
1735+ if (t_tclass == TC_LBRACE) {
1736+ debug_printf_parse("%s: TC_LBRACE\n", __func__);
1737+ chain_until_rbrace();
1738 } else {
1739- debug_printf_parse("%s: !TC_GRPSTART\n", __func__);
1740+ /* no action, assume default "{ print }" */
1741+ debug_printf_parse("%s: !TC_LBRACE\n", __func__);
1742 chain_node(OC_PRINT);
1743 }
1744 cn->r.n = mainseq.last;
1745- } else /* if (tclass & TC_GRPSTART) */ {
1746- debug_printf_parse("%s: TC_GRPSTART(?)\n", __func__);
1747- rollback_token();
1748- chain_group();
1749+ goto next_tok;
1750 }
1751- }
1752- debug_printf_parse("%s: TC_EOF\n", __func__);
1753+ /* tclass == TC_LBRACE */
1754+ debug_printf_parse("%s: TC_LBRACE(?)\n", __func__);
1755+ chain_until_rbrace();
1756+ next_tok:
1757+ /* Same as next_token() at the top of the loop, + TC_SEMICOL */
1758+ tclass = next_token(TS_OPSEQ | TC_LBRACE | TC_BEGIN | TC_END | TC_FUNCDECL
1759+ | TC_EOF | TC_NEWLINE | TC_SEMICOL);
1760+ /* gawk allows many newlines, but does not allow more than one semicolon:
1761+ * BEGIN {...}<newline>;<newline>;
1762+ * would complain "each rule must have a pattern or an action part".
1763+ * Same message for
1764+ * ; BEGIN {...}
1765+ */
1766+ if (tclass != TC_SEMICOL)
1767+ goto got_tok; /* use this token */
1768+ /* else: loop back - ate the semicolon, get and use _next_ token */
1769+ } /* for (;;) */
1770 }
1771
1772-
1773 /* -------- program execution part -------- */
1774
1775+/* temporary variables allocator */
1776+static var *nvalloc(int sz)
1777+{
1778+ return xzalloc(sz * sizeof(var));
1779+}
1780+
1781+static void nvfree(var *v, int sz)
1782+{
1783+ var *p = v;
1784+
1785+ while (--sz >= 0) {
1786+ if ((p->type & (VF_ARRAY | VF_CHILD)) == VF_ARRAY) {
1787+ clear_array(iamarray(p));
1788+ free(p->x.array->items);
1789+ free(p->x.array);
1790+ }
1791+ if (p->type & VF_WALK) {
1792+ walker_list *n;
1793+ walker_list *w = p->x.walker;
1794+ debug_printf_walker("nvfree: freeing walker @%p\n", &p->x.walker);
1795+ p->x.walker = NULL;
1796+ while (w) {
1797+ n = w->prev;
1798+ debug_printf_walker(" free(%p)\n", w);
1799+ free(w);
1800+ w = n;
1801+ }
1802+ }
1803+ clrvar(p);
1804+ p++;
1805+ }
1806+
1807+ free(v);
1808+}
1809+
1810 static node *mk_splitter(const char *s, tsplitter *spl)
1811 {
1812 regex_t *re, *ire;
1813@@ -1686,7 +1848,7 @@ static node *mk_splitter(const char *s, tsplitter *spl)
1814 re = &spl->re[0];
1815 ire = &spl->re[1];
1816 n = &spl->n;
1817- if ((n->info & OPCLSMASK) == OC_REGEXP) {
1818+ if (n->info == TI_REGEXP) {
1819 regfree(re);
1820 regfree(ire); // TODO: nuke ire, use re+1?
1821 }
1822@@ -1699,21 +1861,28 @@ static node *mk_splitter(const char *s, tsplitter *spl)
1823 return n;
1824 }
1825
1826-/* use node as a regular expression. Supplied with node ptr and regex_t
1827+static var *evaluate(node *, var *);
1828+
1829+/* Use node as a regular expression. Supplied with node ptr and regex_t
1830 * storage space. Return ptr to regex (if result points to preg, it should
1831- * be later regfree'd manually
1832+ * be later regfree'd manually).
1833 */
1834 static regex_t *as_regex(node *op, regex_t *preg)
1835 {
1836 int cflags;
1837- var *v;
1838 const char *s;
1839
1840- if ((op->info & OPCLSMASK) == OC_REGEXP) {
1841+ if (op->info == TI_REGEXP) {
1842 return icase ? op->r.ire : op->l.re;
1843 }
1844- v = nvalloc(1);
1845- s = getvar_s(evaluate(op, v));
1846+
1847+ //tmpvar = nvalloc(1);
1848+#define TMPVAR (&G.as_regex__tmpvar)
1849+ // We use a single "static" tmpvar (instead of on-stack or malloced one)
1850+ // to decrease memory consumption in deeply-recursive awk programs.
1851+ // The rule to work safely is to never call evaluate() while our static
1852+ // TMPVAR's value is still needed.
1853+ s = getvar_s(evaluate(op, TMPVAR));
1854
1855 cflags = icase ? REG_EXTENDED | REG_ICASE : REG_EXTENDED;
1856 /* Testcase where REG_EXTENDED fails (unpaired '{'):
1857@@ -1725,7 +1894,8 @@ static regex_t *as_regex(node *op, regex_t *preg)
1858 cflags &= ~REG_EXTENDED;
1859 xregcomp(preg, s, cflags);
1860 }
1861- nvfree(v);
1862+ //nvfree(tmpvar, 1);
1863+#undef TMPVAR
1864 return preg;
1865 }
1866
1867@@ -1745,12 +1915,22 @@ static char* qrealloc(char *b, int n, int *size)
1868 /* resize field storage space */
1869 static void fsrealloc(int size)
1870 {
1871- int i;
1872+ int i, newsize;
1873
1874 if (size >= maxfields) {
1875+ /* Sanity cap, easier than catering for overflows */
1876+ if (size > 0xffffff)
1877+ bb_die_memory_exhausted();
1878+
1879 i = maxfields;
1880 maxfields = size + 16;
1881- Fields = xrealloc(Fields, maxfields * sizeof(Fields[0]));
1882+
1883+ newsize = maxfields * sizeof(Fields[0]);
1884+ debug_printf_eval("fsrealloc: xrealloc(%p, %u)\n", Fields, newsize);
1885+ Fields = xrealloc(Fields, newsize);
1886+ debug_printf_eval("fsrealloc: Fields=%p..%p\n", Fields, (char*)Fields + newsize - 1);
1887+ /* ^^^ did Fields[] move? debug aid for L.v getting "upstaged" by R.v in evaluate() */
1888+
1889 for (; i < maxfields; i++) {
1890 Fields[i].type = VF_SPECIAL;
1891 Fields[i].string = NULL;
1892@@ -1802,13 +1982,13 @@ static int awk_split(const char *s, node *spl, char **slist)
1893 c[2] = '\n';
1894
1895 n = 0;
1896- if ((spl->info & OPCLSMASK) == OC_REGEXP) { /* regex split */
1897+ if (spl->info == TI_REGEXP) { /* regex split */
1898 if (!*s)
1899 return n; /* "": zero fields */
1900 n++; /* at least one field will be there */
1901 do {
1902 int l;
1903- regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
1904+ regmatch_t pmatch[1];
1905
1906 l = strcspn(s, c+2); /* len till next NUL or \n */
1907 if (regexec1_nonempty(icase ? spl->r.ire : spl->l.re, s, pmatch) == 0
1908@@ -1969,7 +2149,7 @@ static node *nextarg(node **pn)
1909 node *n;
1910
1911 n = *pn;
1912- if (n && (n->info & OPCLSMASK) == OC_COMMA) {
1913+ if (n && n->info == TI_COMMA) {
1914 *pn = n->r.n;
1915 n = n->l.n;
1916 } else {
1917@@ -2000,8 +2180,7 @@ static void hashwalk_init(var *v, xhash *array)
1918 for (i = 0; i < array->csize; i++) {
1919 hi = array->items[i];
1920 while (hi) {
1921- strcpy(w->end, hi->name);
1922- nextword(&w->end);
1923+ w->end = stpcpy(w->end, hi->name) + 1;
1924 hi = hi->next;
1925 }
1926 }
1927@@ -2027,15 +2206,18 @@ static int hashwalk_next(var *v)
1928 /* evaluate node, return 1 when result is true, 0 otherwise */
1929 static int ptest(node *pattern)
1930 {
1931- /* ptest__v is "static": to save stack space? */
1932- return istrue(evaluate(pattern, &G.ptest__v));
1933+ // We use a single "static" tmpvar (instead of on-stack or malloced one)
1934+ // to decrease memory consumption in deeply-recursive awk programs.
1935+ // The rule to work safely is to never call evaluate() while our static
1936+ // TMPVAR's value is still needed.
1937+ return istrue(evaluate(pattern, &G.ptest__tmpvar));
1938 }
1939
1940 /* read next record from stream rsm into a variable v */
1941 static int awk_getline(rstream *rsm, var *v)
1942 {
1943 char *b;
1944- regmatch_t pmatch[2]; // TODO: why [2]? [1] is enough...
1945+ regmatch_t pmatch[1];
1946 int size, a, p, pp = 0;
1947 int fd, so, eo, r, rp;
1948 char c, *m, *s;
1949@@ -2061,7 +2243,7 @@ static int awk_getline(rstream *rsm, var *v)
1950 so = eo = p;
1951 r = 1;
1952 if (p > 0) {
1953- if ((rsplitter.n.info & OPCLSMASK) == OC_REGEXP) {
1954+ if (rsplitter.n.info == TI_REGEXP) {
1955 if (regexec(icase ? rsplitter.n.r.ire : rsplitter.n.l.re,
1956 b, 1, pmatch, 0) == 0) {
1957 so = pmatch[0].rm_so;
1958@@ -2133,82 +2315,126 @@ static int awk_getline(rstream *rsm, var *v)
1959 return r;
1960 }
1961
1962-static int fmt_num(char *b, int size, const char *format, double n, int int_as_int)
1963-{
1964- int r = 0;
1965- char c;
1966- const char *s = format;
1967-
1968- if (int_as_int && n == (long long)n) {
1969- r = snprintf(b, size, "%lld", (long long)n);
1970- } else {
1971- do { c = *s; } while (c && *++s);
1972- if (strchr("diouxX", c)) {
1973- r = snprintf(b, size, format, (int)n);
1974- } else if (strchr("eEfgG", c)) {
1975- r = snprintf(b, size, format, n);
1976- } else {
1977- syntax_error(EMSG_INV_FMT);
1978- }
1979- }
1980- return r;
1981-}
1982-
1983 /* formatted output into an allocated buffer, return ptr to buffer */
1984-static char *awk_printf(node *n)
1985+#if !ENABLE_FEATURE_AWK_GNU_EXTENSIONS
1986+# define awk_printf(a, b) awk_printf(a)
1987+#endif
1988+static char *awk_printf(node *n, size_t *len)
1989 {
1990- char *b = NULL;
1991- char *fmt, *s, *f;
1992- const char *s1;
1993- int i, j, incr, bsize;
1994- char c, c1;
1995- var *v, *arg;
1996-
1997- v = nvalloc(1);
1998- fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), v)));
1999-
2000+ char *b;
2001+ char *fmt, *f;
2002+ size_t i;
2003+
2004+ //tmpvar = nvalloc(1);
2005+#define TMPVAR (&G.awk_printf__tmpvar)
2006+ // We use a single "static" tmpvar (instead of on-stack or malloced one)
2007+ // to decrease memory consumption in deeply-recursive awk programs.
2008+ // The rule to work safely is to never call evaluate() while our static
2009+ // TMPVAR's value is still needed.
2010+ fmt = f = xstrdup(getvar_s(evaluate(nextarg(&n), TMPVAR)));
2011+ // ^^^^^^^^^ here we immediately strdup() the value, so the later call
2012+ // to evaluate() potentially recursing into another awk_printf() can't
2013+ // mangle the value.
2014+
2015+ b = NULL;
2016 i = 0;
2017- while (*f) {
2018+ while (1) { /* "print one format spec" loop */
2019+ char *s;
2020+ char c;
2021+ char sv;
2022+ var *arg;
2023+ size_t slen;
2024+
2025+ /* Find end of the next format spec, or end of line */
2026 s = f;
2027- while (*f && (*f != '%' || *++f == '%'))
2028- f++;
2029- while (*f && !isalpha(*f)) {
2030- if (*f == '*')
2031- syntax_error("%*x formats are not supported");
2032+ while (1) {
2033+ c = *f;
2034+ if (!c) /* no percent chars found at all */
2035+ goto nul;
2036 f++;
2037+ if (c == '%')
2038+ break;
2039 }
2040-
2041- incr = (f - s) + MAXVARFMT;
2042- b = qrealloc(b, incr + i, &bsize);
2043+ /* we are past % in "....%..." */
2044 c = *f;
2045- if (c != '\0')
2046+ if (!c) /* "....%" */
2047+ goto nul;
2048+ if (c == '%') { /* "....%%...." */
2049+ slen = f - s;
2050+ s = xstrndup(s, slen);
2051 f++;
2052- c1 = *f;
2053+ goto append; /* print "....%" part verbatim */
2054+ }
2055+ while (1) {
2056+ if (isalpha(c))
2057+ break;
2058+ if (c == '*')
2059+ syntax_error("%*x formats are not supported");
2060+ c = *++f;
2061+ if (!c) { /* "....%...." and no letter found after % */
2062+ /* Example: awk 'BEGIN { printf "^^^%^^^\n"; }' */
2063+ nul:
2064+ slen = f - s;
2065+ goto tail; /* print remaining string, exit loop */
2066+ }
2067+ }
2068+ /* we are at A in "....%...A..." */
2069+
2070+ arg = evaluate(nextarg(&n), TMPVAR);
2071+
2072+ /* Result can be arbitrarily long. Example:
2073+ * printf "%99999s", "BOOM"
2074+ */
2075+ sv = *++f;
2076 *f = '\0';
2077- arg = evaluate(nextarg(&n), v);
2078-
2079- j = i;
2080- if (c == 'c' || !c) {
2081- i += sprintf(b+i, s, is_numeric(arg) ?
2082- (char)getvar_i(arg) : *getvar_s(arg));
2083- } else if (c == 's') {
2084- s1 = getvar_s(arg);
2085- b = qrealloc(b, incr+i+strlen(s1), &bsize);
2086- i += sprintf(b+i, s, s1);
2087+ if (c == 'c') {
2088+ char cc = is_numeric(arg) ? getvar_i(arg) : *getvar_s(arg);
2089+ char *r = xasprintf(s, cc ? cc : '^' /* else strlen will be wrong */);
2090+ slen = strlen(r);
2091+ if (cc == '\0') /* if cc is NUL, re-format the string with it */
2092+ sprintf(r, s, cc);
2093+ s = r;
2094 } else {
2095- i += fmt_num(b+i, incr, s, getvar_i(arg), FALSE);
2096+ if (c == 's') {
2097+ s = xasprintf(s, getvar_s(arg));
2098+ } else {
2099+ double d = getvar_i(arg);
2100+ if (strchr("diouxX", c)) {
2101+//TODO: make it wider here (%x -> %llx etc)?
2102+ s = xasprintf(s, (int)d);
2103+ } else if (strchr("eEfFgGaA", c)) {
2104+ s = xasprintf(s, d);
2105+ } else {
2106+//TODO: GNU Awk 5.0.1: printf "%W" prints "%W", does not error out
2107+ syntax_error(EMSG_INV_FMT);
2108+ }
2109+ }
2110+ slen = strlen(s);
2111 }
2112- *f = c1;
2113-
2114- /* if there was an error while sprintf, return value is negative */
2115- if (i < j)
2116- i = j;
2117+ *f = sv;
2118+ append:
2119+ if (i == 0) {
2120+ b = s;
2121+ i = slen;
2122+ continue;
2123+ }
2124+ tail:
2125+ b = xrealloc(b, i + slen + 1);
2126+ strcpy(b + i, s);
2127+ i += slen;
2128+ if (!c) /* s is NOT allocated and this is the last part of string? */
2129+ break;
2130+ free(s);
2131 }
2132
2133 free(fmt);
2134- nvfree(v);
2135- b = xrealloc(b, i + 1);
2136- b[i] = '\0';
2137+ //nvfree(tmpvar, 1);
2138+#undef TMPVAR
2139+
2140+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2141+ if (len)
2142+ *len = i;
2143+#endif
2144 return b;
2145 }
2146
2147@@ -2338,33 +2564,59 @@ static NOINLINE int do_mktime(const char *ds)
2148 return mktime(&then);
2149 }
2150
2151+/* Reduce stack usage in exec_builtin() by keeping match() code separate */
2152+static NOINLINE var *do_match(node *an1, const char *as0)
2153+{
2154+ regmatch_t pmatch[1];
2155+ regex_t sreg, *re;
2156+ int n, start, len;
2157+
2158+ re = as_regex(an1, &sreg);
2159+ n = regexec(re, as0, 1, pmatch, 0);
2160+ if (re == &sreg)
2161+ regfree(re);
2162+ start = 0;
2163+ len = -1;
2164+ if (n == 0) {
2165+ start = pmatch[0].rm_so + 1;
2166+ len = pmatch[0].rm_eo - pmatch[0].rm_so;
2167+ }
2168+ setvar_i(newvar("RLENGTH"), len);
2169+ return setvar_i(newvar("RSTART"), start);
2170+}
2171+
2172+/* Reduce stack usage in evaluate() by keeping builtins' code separate */
2173 static NOINLINE var *exec_builtin(node *op, var *res)
2174 {
2175 #define tspl (G.exec_builtin__tspl)
2176
2177- var *tv;
2178+ var *tmpvars;
2179 node *an[4];
2180 var *av[4];
2181 const char *as[4];
2182- regmatch_t pmatch[2];
2183- regex_t sreg, *re;
2184 node *spl;
2185 uint32_t isr, info;
2186 int nargs;
2187 time_t tt;
2188 int i, l, ll, n;
2189
2190- tv = nvalloc(4);
2191+ tmpvars = nvalloc(4);
2192+#define TMPVAR0 (tmpvars)
2193+#define TMPVAR1 (tmpvars + 1)
2194+#define TMPVAR2 (tmpvars + 2)
2195+#define TMPVAR3 (tmpvars + 3)
2196+#define TMPVAR(i) (tmpvars + (i))
2197 isr = info = op->info;
2198 op = op->l.n;
2199
2200 av[2] = av[3] = NULL;
2201 for (i = 0; i < 4 && op; i++) {
2202 an[i] = nextarg(&op);
2203- if (isr & 0x09000000)
2204- av[i] = evaluate(an[i], &tv[i]);
2205- if (isr & 0x08000000)
2206- as[i] = getvar_s(av[i]);
2207+ if (isr & 0x09000000) {
2208+ av[i] = evaluate(an[i], TMPVAR(i));
2209+ if (isr & 0x08000000)
2210+ as[i] = getvar_s(av[i]);
2211+ }
2212 isr >>= 1;
2213 }
2214
2215@@ -2386,8 +2638,8 @@ static NOINLINE var *exec_builtin(node *op, var *res)
2216 char *s, *s1;
2217
2218 if (nargs > 2) {
2219- spl = (an[2]->info & OPCLSMASK) == OC_REGEXP ?
2220- an[2] : mk_splitter(getvar_s(evaluate(an[2], &tv[2])), &tspl);
2221+ spl = (an[2]->info == TI_REGEXP) ? an[2]
2222+ : mk_splitter(getvar_s(evaluate(an[2], TMPVAR2)), &tspl);
2223 } else {
2224 spl = &fsplitter.n;
2225 }
2226@@ -2501,20 +2753,7 @@ static NOINLINE var *exec_builtin(node *op, var *res)
2227 break;
2228
2229 case B_ma:
2230- re = as_regex(an[1], &sreg);
2231- n = regexec(re, as[0], 1, pmatch, 0);
2232- if (n == 0) {
2233- pmatch[0].rm_so++;
2234- pmatch[0].rm_eo++;
2235- } else {
2236- pmatch[0].rm_so = 0;
2237- pmatch[0].rm_eo = -1;
2238- }
2239- setvar_i(newvar("RSTART"), pmatch[0].rm_so);
2240- setvar_i(newvar("RLENGTH"), pmatch[0].rm_eo - pmatch[0].rm_so);
2241- setvar_i(res, pmatch[0].rm_so);
2242- if (re == &sreg)
2243- regfree(re);
2244+ res = do_match(an[1], as[0]);
2245 break;
2246
2247 case B_ge:
2248@@ -2530,14 +2769,79 @@ static NOINLINE var *exec_builtin(node *op, var *res)
2249 break;
2250 }
2251
2252- nvfree(tv);
2253+ nvfree(tmpvars, 4);
2254+#undef TMPVAR0
2255+#undef TMPVAR1
2256+#undef TMPVAR2
2257+#undef TMPVAR3
2258+#undef TMPVAR
2259+
2260 return res;
2261 #undef tspl
2262 }
2263
2264+/* if expr looks like "var=value", perform assignment and return 1,
2265+ * otherwise return 0 */
2266+static int is_assignment(const char *expr)
2267+{
2268+ char *exprc, *val;
2269+
2270+ val = (char*)endofname(expr);
2271+ if (val == (char*)expr || *val != '=') {
2272+ return FALSE;
2273+ }
2274+
2275+ exprc = xstrdup(expr);
2276+ val = exprc + (val - expr);
2277+ *val++ = '\0';
2278+
2279+ unescape_string_in_place(val);
2280+ setvar_u(newvar(exprc), val);
2281+ free(exprc);
2282+ return TRUE;
2283+}
2284+
2285+/* switch to next input file */
2286+static rstream *next_input_file(void)
2287+{
2288+#define rsm (G.next_input_file__rsm)
2289+#define files_happen (G.next_input_file__files_happen)
2290+
2291+ const char *fname, *ind;
2292+
2293+ if (rsm.F)
2294+ fclose(rsm.F);
2295+ rsm.F = NULL;
2296+ rsm.pos = rsm.adv = 0;
2297+
2298+ for (;;) {
2299+ if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
2300+ if (files_happen)
2301+ return NULL;
2302+ fname = "-";
2303+ rsm.F = stdin;
2304+ break;
2305+ }
2306+ ind = getvar_s(incvar(intvar[ARGIND]));
2307+ fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
2308+ if (fname && *fname && !is_assignment(fname)) {
2309+ rsm.F = xfopen_stdin(fname);
2310+ break;
2311+ }
2312+ }
2313+
2314+ files_happen = TRUE;
2315+ setvar_s(intvar[FILENAME], fname);
2316+ return &rsm;
2317+#undef rsm
2318+#undef files_happen
2319+}
2320+
2321 /*
2322 * Evaluate node - the heart of the program. Supplied with subtree
2323- * and place where to store result. returns ptr to result.
2324+ * and "res" variable to assign the result to if we evaluate an expression.
2325+ * If node refers to e.g. a variable or a field, no assignment happens.
2326+ * Return ptr to the result (which may or may not be the "res" variable!)
2327 */
2328 #define XC(n) ((n) >> 8)
2329
2330@@ -2549,14 +2853,16 @@ static var *evaluate(node *op, var *res)
2331 #define seed (G.evaluate__seed)
2332 #define sreg (G.evaluate__sreg)
2333
2334- var *v1;
2335+ var *tmpvars;
2336
2337 if (!op)
2338 return setvar_s(res, NULL);
2339
2340 debug_printf_eval("entered %s()\n", __func__);
2341
2342- v1 = nvalloc(2);
2343+ tmpvars = nvalloc(2);
2344+#define TMPVAR0 (tmpvars)
2345+#define TMPVAR1 (tmpvars + 1)
2346
2347 while (op) {
2348 struct {
2349@@ -2578,48 +2884,35 @@ static var *evaluate(node *op, var *res)
2350 op1 = op->l.n;
2351 debug_printf_eval("opinfo:%08x opn:%08x\n", opinfo, opn);
2352
2353- /* "delete" is special:
2354- * "delete array[var--]" must evaluate index expr only once,
2355- * must not evaluate it in "execute inevitable things" part.
2356- */
2357- if (XC(opinfo & OPCLSMASK) == XC(OC_DELETE)) {
2358- uint32_t info = op1->info & OPCLSMASK;
2359- var *v;
2360-
2361- debug_printf_eval("DELETE\n");
2362- if (info == OC_VAR) {
2363- v = op1->l.v;
2364- } else if (info == OC_FNARG) {
2365- v = &fnargs[op1->l.aidx];
2366- } else {
2367- syntax_error(EMSG_NOT_ARRAY);
2368+ /* execute inevitable things */
2369+ if (opinfo & OF_RES1) {
2370+ if ((opinfo & OF_REQUIRED) && !op1)
2371+ syntax_error(EMSG_TOO_FEW_ARGS);
2372+ L.v = evaluate(op1, TMPVAR0);
2373+ if (opinfo & OF_STR1) {
2374+ L.s = getvar_s(L.v);
2375+ debug_printf_eval("L.s:'%s'\n", L.s);
2376 }
2377- if (op1->r.n) { /* array ref? */
2378- const char *s;
2379- s = getvar_s(evaluate(op1->r.n, v1));
2380- hash_remove(iamarray(v), s);
2381- } else {
2382- clear_array(iamarray(v));
2383+ if (opinfo & OF_NUM1) {
2384+ L_d = getvar_i(L.v);
2385+ debug_printf_eval("L_d:%f\n", L_d);
2386 }
2387- goto next;
2388 }
2389-
2390- /* execute inevitable things */
2391- if (opinfo & OF_RES1)
2392- L.v = evaluate(op1, v1);
2393- if (opinfo & OF_RES2)
2394- R.v = evaluate(op->r.n, v1+1);
2395- if (opinfo & OF_STR1) {
2396- L.s = getvar_s(L.v);
2397- debug_printf_eval("L.s:'%s'\n", L.s);
2398- }
2399- if (opinfo & OF_STR2) {
2400- R.s = getvar_s(R.v);
2401- debug_printf_eval("R.s:'%s'\n", R.s);
2402- }
2403- if (opinfo & OF_NUM1) {
2404- L_d = getvar_i(L.v);
2405- debug_printf_eval("L_d:%f\n", L_d);
2406+ /* NB: Must get string/numeric values of L (done above)
2407+ * _before_ evaluate()'ing R.v: if both L and R are $NNNs,
2408+ * and right one is large, then L.v points to Fields[NNN1],
2409+ * second evaluate() reallocates and moves (!) Fields[],
2410+ * R.v points to Fields[NNN2] but L.v now points to freed mem!
2411+ * (Seen trying to evaluate "$444 $44444")
2412+ */
2413+ if (opinfo & OF_RES2) {
2414+ R.v = evaluate(op->r.n, TMPVAR1);
2415+ //TODO: L.v may be invalid now, set L.v to NULL to catch bugs?
2416+ //L.v = NULL;
2417+ if (opinfo & OF_STR2) {
2418+ R.s = getvar_s(R.v);
2419+ debug_printf_eval("R.s:'%s'\n", R.s);
2420+ }
2421 }
2422
2423 debug_printf_eval("switch(0x%x)\n", XC(opinfo & OPCLSMASK));
2424@@ -2629,7 +2922,8 @@ static var *evaluate(node *op, var *res)
2425
2426 /* test pattern */
2427 case XC( OC_TEST ):
2428- if ((op1->info & OPCLSMASK) == OC_COMMA) {
2429+ debug_printf_eval("TEST\n");
2430+ if (op1->info == TI_COMMA) {
2431 /* it's range pattern */
2432 if ((opinfo & OF_CHECKED) || ptest(op1->l.n)) {
2433 op->info |= OF_CHECKED;
2434@@ -2646,25 +2940,32 @@ static var *evaluate(node *op, var *res)
2435
2436 /* just evaluate an expression, also used as unconditional jump */
2437 case XC( OC_EXEC ):
2438+ debug_printf_eval("EXEC\n");
2439 break;
2440
2441 /* branch, used in if-else and various loops */
2442 case XC( OC_BR ):
2443+ debug_printf_eval("BR\n");
2444 op = istrue(L.v) ? op->a.n : op->r.n;
2445 break;
2446
2447 /* initialize for-in loop */
2448 case XC( OC_WALKINIT ):
2449+ debug_printf_eval("WALKINIT\n");
2450 hashwalk_init(L.v, iamarray(R.v));
2451 break;
2452
2453 /* get next array item */
2454 case XC( OC_WALKNEXT ):
2455+ debug_printf_eval("WALKNEXT\n");
2456 op = hashwalk_next(L.v) ? op->a.n : op->r.n;
2457 break;
2458
2459 case XC( OC_PRINT ):
2460- case XC( OC_PRINTF ): {
2461+ debug_printf_eval("PRINT /\n");
2462+ case XC( OC_PRINTF ):
2463+ debug_printf_eval("PRINTF\n");
2464+ {
2465 FILE *F = stdout;
2466
2467 if (op->r.n) {
2468@@ -2682,55 +2983,94 @@ static var *evaluate(node *op, var *res)
2469 F = rsm->F;
2470 }
2471
2472+ /* Can't just check 'opinfo == OC_PRINT' here, parser ORs
2473+ * additional bits to opinfos of print/printf with redirects
2474+ */
2475 if ((opinfo & OPCLSMASK) == OC_PRINT) {
2476 if (!op1) {
2477 fputs(getvar_s(intvar[F0]), F);
2478 } else {
2479- while (op1) {
2480- var *v = evaluate(nextarg(&op1), v1);
2481+ for (;;) {
2482+ var *v = evaluate(nextarg(&op1), TMPVAR0);
2483 if (v->type & VF_NUMBER) {
2484- fmt_num(g_buf, MAXVARFMT, getvar_s(intvar[OFMT]),
2485- getvar_i(v), TRUE);
2486+ fmt_num(getvar_s(intvar[OFMT]),
2487+ getvar_i(v));
2488 fputs(g_buf, F);
2489 } else {
2490 fputs(getvar_s(v), F);
2491 }
2492-
2493- if (op1)
2494- fputs(getvar_s(intvar[OFS]), F);
2495+ if (!op1)
2496+ break;
2497+ fputs(getvar_s(intvar[OFS]), F);
2498 }
2499 }
2500 fputs(getvar_s(intvar[ORS]), F);
2501-
2502- } else { /* OC_PRINTF */
2503- char *s = awk_printf(op1);
2504+ } else { /* PRINTF */
2505+ IF_FEATURE_AWK_GNU_EXTENSIONS(size_t len;)
2506+ char *s = awk_printf(op1, &len);
2507+#if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2508+ fwrite(s, len, 1, F);
2509+#else
2510 fputs(s, F);
2511+#endif
2512 free(s);
2513 }
2514 fflush(F);
2515 break;
2516 }
2517
2518- /* case XC( OC_DELETE ): - moved to happen before arg evaluation */
2519+ case XC( OC_DELETE ):
2520+ debug_printf_eval("DELETE\n");
2521+ {
2522+ /* "delete" is special:
2523+ * "delete array[var--]" must evaluate index expr only once.
2524+ */
2525+ uint32_t info = op1->info & OPCLSMASK;
2526+ var *v;
2527+
2528+ if (info == OC_VAR) {
2529+ v = op1->l.v;
2530+ } else if (info == OC_FNARG) {
2531+ v = &fnargs[op1->l.aidx];
2532+ } else {
2533+ syntax_error(EMSG_NOT_ARRAY);
2534+ }
2535+ if (op1->r.n) { /* array ref? */
2536+ const char *s;
2537+ s = getvar_s(evaluate(op1->r.n, TMPVAR0));
2538+ hash_remove(iamarray(v), s);
2539+ } else {
2540+ clear_array(iamarray(v));
2541+ }
2542+ break;
2543+ }
2544
2545 case XC( OC_NEWSOURCE ):
2546+ debug_printf_eval("NEWSOURCE\n");
2547 g_progname = op->l.new_progname;
2548 break;
2549
2550 case XC( OC_RETURN ):
2551+ debug_printf_eval("RETURN\n");
2552 copyvar(res, L.v);
2553 break;
2554
2555 case XC( OC_NEXTFILE ):
2556+ debug_printf_eval("NEXTFILE\n");
2557 nextfile = TRUE;
2558 case XC( OC_NEXT ):
2559+ debug_printf_eval("NEXT\n");
2560 nextrec = TRUE;
2561 case XC( OC_DONE ):
2562+ debug_printf_eval("DONE\n");
2563 clrvar(res);
2564 break;
2565
2566 case XC( OC_EXIT ):
2567- awk_exit(L_d);
2568+ debug_printf_eval("EXIT\n");
2569+ if (op1)
2570+ G.exitcode = (int)L_d;
2571+ awk_exit();
2572
2573 /* -- recursive node type -- */
2574
2575@@ -2749,15 +3089,18 @@ static var *evaluate(node *op, var *res)
2576 break;
2577
2578 case XC( OC_IN ):
2579+ debug_printf_eval("IN\n");
2580 setvar_i(res, hash_search(iamarray(R.v), L.s) ? 1 : 0);
2581 break;
2582
2583 case XC( OC_REGEXP ):
2584+ debug_printf_eval("REGEXP\n");
2585 op1 = op;
2586 L.s = getvar_s(intvar[F0]);
2587 goto re_cont;
2588
2589 case XC( OC_MATCH ):
2590+ debug_printf_eval("MATCH\n");
2591 op1 = op->r.n;
2592 re_cont:
2593 {
2594@@ -2772,61 +3115,80 @@ static var *evaluate(node *op, var *res)
2595 case XC( OC_MOVE ):
2596 debug_printf_eval("MOVE\n");
2597 /* if source is a temporary string, jusk relink it to dest */
2598-//Disabled: if R.v is numeric but happens to have cached R.v->string,
2599-//then L.v ends up being a string, which is wrong
2600-// if (R.v == v1+1 && R.v->string) {
2601-// res = setvar_p(L.v, R.v->string);
2602-// R.v->string = NULL;
2603-// } else {
2604+ if (R.v == TMPVAR1
2605+ && !(R.v->type & VF_NUMBER)
2606+ /* Why check !NUMBER? if R.v is a number but has cached R.v->string,
2607+ * L.v ends up a string, which is wrong */
2608+ /*&& R.v->string - always not NULL (right?) */
2609+ ) {
2610+ res = setvar_p(L.v, R.v->string); /* avoids strdup */
2611+ R.v->string = NULL;
2612+ } else {
2613 res = copyvar(L.v, R.v);
2614-// }
2615+ }
2616 break;
2617
2618 case XC( OC_TERNARY ):
2619- if ((op->r.n->info & OPCLSMASK) != OC_COLON)
2620+ debug_printf_eval("TERNARY\n");
2621+ if (op->r.n->info != TI_COLON)
2622 syntax_error(EMSG_POSSIBLE_ERROR);
2623 res = evaluate(istrue(L.v) ? op->r.n->l.n : op->r.n->r.n, res);
2624 break;
2625
2626 case XC( OC_FUNC ): {
2627- var *vbeg, *v;
2628+ var *argvars, *sv_fnargs;
2629 const char *sv_progname;
2630+ int nargs, i;
2631
2632- /* The body might be empty, still has to eval the args */
2633- if (!op->r.n->info && !op->r.f->body.first)
2634+ debug_printf_eval("FUNC\n");
2635+
2636+ if (!op->r.f->defined)
2637 syntax_error(EMSG_UNDEF_FUNC);
2638
2639- vbeg = v = nvalloc(op->r.f->nargs + 1);
2640+ /* The body might be empty, still has to eval the args */
2641+ nargs = op->r.f->nargs;
2642+ argvars = nvalloc(nargs);
2643+ i = 0;
2644 while (op1) {
2645- var *arg = evaluate(nextarg(&op1), v1);
2646- copyvar(v, arg);
2647- v->type |= VF_CHILD;
2648- v->x.parent = arg;
2649- if (++v - vbeg >= op->r.f->nargs)
2650- break;
2651+ var *arg = evaluate(nextarg(&op1), TMPVAR0);
2652+ if (i == nargs) {
2653+ /* call with more arguments than function takes.
2654+ * (gawk warns: "warning: function 'f' called with more arguments than declared").
2655+ * They are still evaluated, but discarded: */
2656+ clrvar(arg);
2657+ continue;
2658+ }
2659+ copyvar(&argvars[i], arg);
2660+ argvars[i].type |= VF_CHILD;
2661+ argvars[i].x.parent = arg;
2662+ i++;
2663 }
2664
2665- v = fnargs;
2666- fnargs = vbeg;
2667+ sv_fnargs = fnargs;
2668 sv_progname = g_progname;
2669
2670+ fnargs = argvars;
2671 res = evaluate(op->r.f->body.first, res);
2672+ nvfree(argvars, nargs);
2673
2674 g_progname = sv_progname;
2675- nvfree(fnargs);
2676- fnargs = v;
2677+ fnargs = sv_fnargs;
2678
2679 break;
2680 }
2681
2682 case XC( OC_GETLINE ):
2683- case XC( OC_PGETLINE ): {
2684+ debug_printf_eval("GETLINE /\n");
2685+ case XC( OC_PGETLINE ):
2686+ debug_printf_eval("PGETLINE\n");
2687+ {
2688 rstream *rsm;
2689 int i;
2690
2691 if (op1) {
2692 rsm = newfile(L.s);
2693 if (!rsm->F) {
2694+ /* NB: can't use "opinfo == TI_PGETLINE", would break "cmd" | getline */
2695 if ((opinfo & OPCLSMASK) == OC_PGETLINE) {
2696 rsm->F = popen(L.s, "r");
2697 rsm->is_pipe = TRUE;
2698@@ -2861,16 +3223,34 @@ static var *evaluate(node *op, var *res)
2699 /* simple builtins */
2700 case XC( OC_FBLTIN ): {
2701 double R_d = R_d; /* for compiler */
2702+ debug_printf_eval("FBLTIN\n");
2703+
2704+ if (op1 && op1->info == TI_COMMA)
2705+ /* Simple builtins take one arg maximum */
2706+ syntax_error("Too many arguments");
2707
2708 switch (opn) {
2709 case F_in:
2710 R_d = (long long)L_d;
2711 break;
2712
2713- case F_rn:
2714- R_d = (double)rand() / (double)RAND_MAX;
2715+ case F_rn: /*rand*/
2716+ if (op1)
2717+ syntax_error("Too many arguments");
2718+ {
2719+#if RAND_MAX >= 0x7fffffff
2720+ uint32_t u = ((uint32_t)rand() << 16) ^ rand();
2721+ uint64_t v = ((uint64_t)rand() << 32) | u;
2722+ /* the above shift+or is optimized out on 32-bit arches */
2723+# if RAND_MAX > 0x7fffffff
2724+ v &= 0x7fffffffffffffffULL;
2725+# endif
2726+ R_d = (double)v / 0x8000000000000000ULL;
2727+#else
2728+# error Not implemented for this value of RAND_MAX
2729+#endif
2730 break;
2731-
2732+ }
2733 case F_co:
2734 if (ENABLE_FEATURE_AWK_LIBM) {
2735 R_d = cos(L_d);
2736@@ -2910,7 +3290,9 @@ static var *evaluate(node *op, var *res)
2737 srand(seed);
2738 break;
2739
2740- case F_ti:
2741+ case F_ti: /*systime*/
2742+ if (op1)
2743+ syntax_error("Too many arguments");
2744 R_d = time(NULL);
2745 break;
2746
2747@@ -2949,7 +3331,7 @@ static var *evaluate(node *op, var *res)
2748 rstream *rsm;
2749 int err = 0;
2750 rsm = (rstream *)hash_search(fdhash, L.s);
2751- debug_printf_eval("OC_FBLTIN F_cl rsm:%p\n", rsm);
2752+ debug_printf_eval("OC_FBLTIN close: op1:%p s:'%s' rsm:%p\n", op1, L.s, rsm);
2753 if (rsm) {
2754 debug_printf_eval("OC_FBLTIN F_cl "
2755 "rsm->is_pipe:%d, ->F:%p\n",
2756@@ -2960,6 +3342,11 @@ static var *evaluate(node *op, var *res)
2757 */
2758 if (rsm->F)
2759 err = rsm->is_pipe ? pclose(rsm->F) : fclose(rsm->F);
2760+//TODO: fix this case:
2761+// $ awk 'BEGIN { print close(""); print ERRNO }'
2762+// -1
2763+// close of redirection that was never opened
2764+// (we print 0, 0)
2765 free(rsm->buffer);
2766 hash_remove(fdhash, L.s);
2767 }
2768@@ -2974,14 +3361,18 @@ static var *evaluate(node *op, var *res)
2769 }
2770
2771 case XC( OC_BUILTIN ):
2772+ debug_printf_eval("BUILTIN\n");
2773 res = exec_builtin(op, res);
2774 break;
2775
2776 case XC( OC_SPRINTF ):
2777- setvar_p(res, awk_printf(op1));
2778+ debug_printf_eval("SPRINTF\n");
2779+ setvar_p(res, awk_printf(op1, NULL));
2780 break;
2781
2782- case XC( OC_UNARY ): {
2783+ case XC( OC_UNARY ):
2784+ debug_printf_eval("UNARY\n");
2785+ {
2786 double Ld, R_d;
2787
2788 Ld = R_d = getvar_i(R.v);
2789@@ -3011,7 +3402,9 @@ static var *evaluate(node *op, var *res)
2790 break;
2791 }
2792
2793- case XC( OC_FIELD ): {
2794+ case XC( OC_FIELD ):
2795+ debug_printf_eval("FIELD\n");
2796+ {
2797 int i = (int)getvar_i(R.v);
2798 if (i < 0)
2799 syntax_error(EMSG_NEGATIVE_FIELD);
2800@@ -3028,26 +3421,33 @@ static var *evaluate(node *op, var *res)
2801
2802 /* concatenation (" ") and index joining (",") */
2803 case XC( OC_CONCAT ):
2804+ debug_printf_eval("CONCAT /\n");
2805 case XC( OC_COMMA ): {
2806 const char *sep = "";
2807- if ((opinfo & OPCLSMASK) == OC_COMMA)
2808+ debug_printf_eval("COMMA\n");
2809+ if (opinfo == TI_COMMA)
2810 sep = getvar_s(intvar[SUBSEP]);
2811 setvar_p(res, xasprintf("%s%s%s", L.s, sep, R.s));
2812 break;
2813 }
2814
2815 case XC( OC_LAND ):
2816+ debug_printf_eval("LAND\n");
2817 setvar_i(res, istrue(L.v) ? ptest(op->r.n) : 0);
2818 break;
2819
2820 case XC( OC_LOR ):
2821+ debug_printf_eval("LOR\n");
2822 setvar_i(res, istrue(L.v) ? 1 : ptest(op->r.n));
2823 break;
2824
2825 case XC( OC_BINARY ):
2826- case XC( OC_REPLACE ): {
2827+ debug_printf_eval("BINARY /\n");
2828+ case XC( OC_REPLACE ):
2829+ debug_printf_eval("REPLACE\n");
2830+ {
2831 double R_d = getvar_i(R.v);
2832- debug_printf_eval("BINARY/REPLACE: R_d:%f opn:%c\n", R_d, opn);
2833+ debug_printf_eval("R_d:%f opn:%c\n", R_d, opn);
2834 switch (opn) {
2835 case '+':
2836 L_d += R_d;
2837@@ -3083,6 +3483,7 @@ static var *evaluate(node *op, var *res)
2838 case XC( OC_COMPARE ): {
2839 int i = i; /* for compiler */
2840 double Ld;
2841+ debug_printf_eval("COMPARE\n");
2842
2843 if (is_numeric(L.v) && is_numeric(R.v)) {
2844 Ld = getvar_i(L.v) - getvar_i(R.v);
2845@@ -3109,7 +3510,7 @@ static var *evaluate(node *op, var *res)
2846 default:
2847 syntax_error(EMSG_POSSIBLE_ERROR);
2848 } /* switch */
2849- next:
2850+
2851 if ((opinfo & OPCLSMASK) <= SHIFT_TIL_THIS)
2852 op = op->a.n;
2853 if ((opinfo & OPCLSMASK) >= RECUR_FROM_THIS)
2854@@ -3118,7 +3519,10 @@ static var *evaluate(node *op, var *res)
2855 break;
2856 } /* while (op) */
2857
2858- nvfree(v1);
2859+ nvfree(tmpvars, 2);
2860+#undef TMPVAR0
2861+#undef TMPVAR1
2862+
2863 debug_printf_eval("returning from %s(): %p\n", __func__, res);
2864 return res;
2865 #undef fnargs
2866@@ -3126,25 +3530,21 @@ static var *evaluate(node *op, var *res)
2867 #undef sreg
2868 }
2869
2870-
2871 /* -------- main & co. -------- */
2872
2873-static int awk_exit(int r)
2874+static int awk_exit(void)
2875 {
2876- var tv;
2877 unsigned i;
2878- hash_item *hi;
2879-
2880- zero_out_var(&tv);
2881
2882 if (!exiting) {
2883 exiting = TRUE;
2884 nextrec = FALSE;
2885- evaluate(endseq.first, &tv);
2886+ evaluate(endseq.first, &G.exit__tmpvar);
2887 }
2888
2889 /* waiting for children */
2890 for (i = 0; i < fdhash->csize; i++) {
2891+ hash_item *hi;
2892 hi = fdhash->items[i];
2893 while (hi) {
2894 if (hi->data.rs.F && hi->data.rs.is_pipe)
2895@@ -3153,65 +3553,7 @@ static int awk_exit(int r)
2896 }
2897 }
2898
2899- exit(r);
2900-}
2901-
2902-/* if expr looks like "var=value", perform assignment and return 1,
2903- * otherwise return 0 */
2904-static int is_assignment(const char *expr)
2905-{
2906- char *exprc, *val;
2907-
2908- if (!isalnum_(*expr) || (val = strchr(expr, '=')) == NULL) {
2909- return FALSE;
2910- }
2911-
2912- exprc = xstrdup(expr);
2913- val = exprc + (val - expr);
2914- *val++ = '\0';
2915-
2916- unescape_string_in_place(val);
2917- setvar_u(newvar(exprc), val);
2918- free(exprc);
2919- return TRUE;
2920-}
2921-
2922-/* switch to next input file */
2923-static rstream *next_input_file(void)
2924-{
2925-#define rsm (G.next_input_file__rsm)
2926-#define files_happen (G.next_input_file__files_happen)
2927-
2928- FILE *F;
2929- const char *fname, *ind;
2930-
2931- if (rsm.F)
2932- fclose(rsm.F);
2933- rsm.F = NULL;
2934- rsm.pos = rsm.adv = 0;
2935-
2936- for (;;) {
2937- if (getvar_i(intvar[ARGIND])+1 >= getvar_i(intvar[ARGC])) {
2938- if (files_happen)
2939- return NULL;
2940- fname = "-";
2941- F = stdin;
2942- break;
2943- }
2944- ind = getvar_s(incvar(intvar[ARGIND]));
2945- fname = getvar_s(findvar(iamarray(intvar[ARGV]), ind));
2946- if (fname && *fname && !is_assignment(fname)) {
2947- F = xfopen_stdin(fname);
2948- break;
2949- }
2950- }
2951-
2952- files_happen = TRUE;
2953- setvar_s(intvar[FILENAME], fname);
2954- rsm.F = F;
2955- return &rsm;
2956-#undef rsm
2957-#undef files_happen
2958+ exit(G.exitcode);
2959 }
2960
2961 int awk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
2962@@ -3224,12 +3566,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
2963 #if ENABLE_FEATURE_AWK_GNU_EXTENSIONS
2964 llist_t *list_e = NULL;
2965 #endif
2966- int i, j;
2967- var *v;
2968- var tv;
2969- char **envp;
2970- char *vnames = (char *)vNames; /* cheat */
2971- char *vvalues = (char *)vValues;
2972+ int i;
2973
2974 INIT_G();
2975
2976@@ -3238,48 +3575,43 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
2977 if (ENABLE_LOCALE_SUPPORT)
2978 setlocale(LC_NUMERIC, "C");
2979
2980- zero_out_var(&tv);
2981-
2982- /* allocate global buffer */
2983- g_buf = xmalloc(MAXVARFMT + 1);
2984-
2985- vhash = hash_init();
2986- ahash = hash_init();
2987- fdhash = hash_init();
2988- fnhash = hash_init();
2989-
2990 /* initialize variables */
2991- for (i = 0; *vnames; i++) {
2992- intvar[i] = v = newvar(nextword(&vnames));
2993- if (*vvalues != '\377')
2994- setvar_s(v, nextword(&vvalues));
2995- else
2996- setvar_i(v, 0);
2997-
2998- if (*vnames == '*') {
2999- v->type |= VF_SPECIAL;
3000- vnames++;
3001+ vhash = hash_init();
3002+ {
3003+ char *vnames = (char *)vNames; /* cheat */
3004+ char *vvalues = (char *)vValues;
3005+ for (i = 0; *vnames; i++) {
3006+ var *v;
3007+ intvar[i] = v = newvar(nextword(&vnames));
3008+ if (*vvalues != '\377')
3009+ setvar_s(v, nextword(&vvalues));
3010+ else
3011+ setvar_i(v, 0);
3012+
3013+ if (*vnames == '*') {
3014+ v->type |= VF_SPECIAL;
3015+ vnames++;
3016+ }
3017 }
3018 }
3019
3020 handle_special(intvar[FS]);
3021 handle_special(intvar[RS]);
3022
3023- newfile("/dev/stdin")->F = stdin;
3024- newfile("/dev/stdout")->F = stdout;
3025- newfile("/dev/stderr")->F = stderr;
3026-
3027 /* Huh, people report that sometimes environ is NULL. Oh well. */
3028- if (environ) for (envp = environ; *envp; envp++) {
3029- /* environ is writable, thus we don't strdup it needlessly */
3030- char *s = *envp;
3031- char *s1 = strchr(s, '=');
3032- if (s1) {
3033- *s1 = '\0';
3034- /* Both findvar and setvar_u take const char*
3035- * as 2nd arg -> environment is not trashed */
3036- setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1);
3037- *s1 = '=';
3038+ if (environ) {
3039+ char **envp;
3040+ for (envp = environ; *envp; envp++) {
3041+ /* environ is writable, thus we don't strdup it needlessly */
3042+ char *s = *envp;
3043+ char *s1 = strchr(s, '=');
3044+ if (s1) {
3045+ *s1 = '\0';
3046+ /* Both findvar and setvar_u take const char*
3047+ * as 2nd arg -> environment is not trashed */
3048+ setvar_u(findvar(iamarray(intvar[ENVIRON]), s), s1 + 1);
3049+ *s1 = '=';
3050+ }
3051 }
3052 }
3053 opt = getopt32(argv, OPTSTR_AWK, &opt_F, &list_v, &list_f, IF_FEATURE_AWK_GNU_EXTENSIONS(&list_e,) NULL);
3054@@ -3295,20 +3627,19 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3055 if (!is_assignment(llist_pop(&list_v)))
3056 bb_show_usage();
3057 }
3058+
3059+ /* Parse all supplied programs */
3060+ fnhash = hash_init();
3061+ ahash = hash_init();
3062 while (list_f) {
3063- char *s = NULL;
3064- FILE *from_file;
3065+ int fd;
3066+ char *s;
3067
3068 g_progname = llist_pop(&list_f);
3069- from_file = xfopen_stdin(g_progname);
3070- /* one byte is reserved for some trick in next_token */
3071- for (i = j = 1; j > 0; i += j) {
3072- s = xrealloc(s, i + 4096);
3073- j = fread(s + i, 1, 4094, from_file);
3074- }
3075- s[i] = '\0';
3076- fclose(from_file);
3077- parse_program(s + 1);
3078+ fd = xopen_stdin(g_progname);
3079+ s = xmalloc_read(fd, NULL); /* it's NUL-terminated */
3080+ close(fd);
3081+ parse_program(s);
3082 free(s);
3083 }
3084 g_progname = "cmd. line";
3085@@ -3317,11 +3648,23 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3086 parse_program(llist_pop(&list_e));
3087 }
3088 #endif
3089+//FIXME: preserve order of -e and -f
3090+//TODO: implement -i LIBRARY and -E FILE too, they are easy-ish
3091 if (!(opt & (OPT_f | OPT_e))) {
3092 if (!*argv)
3093 bb_show_usage();
3094 parse_program(*argv++);
3095 }
3096+ /* Free unused parse structures */
3097+ //hash_free(fnhash); // ~250 bytes when empty, used only for function names
3098+ //^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs
3099+ // (IOW: hash_clear() assumes it's a hash of variables. fnhash is not).
3100+ free(fnhash->items);
3101+ free(fnhash);
3102+ fnhash = NULL; // debug
3103+ //hash_free(ahash); // empty after parsing, will reuse as fdhash instead of freeing
3104+
3105+ /* Parsing done, on to executing */
3106
3107 /* fill in ARGV array */
3108 setari_u(intvar[ARGV], 0, "awk");
3109@@ -3330,9 +3673,14 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3110 setari_u(intvar[ARGV], ++i, *argv++);
3111 setvar_i(intvar[ARGC], i + 1);
3112
3113- evaluate(beginseq.first, &tv);
3114+ //fdhash = ahash; // done via define
3115+ newfile("/dev/stdin")->F = stdin;
3116+ newfile("/dev/stdout")->F = stdout;
3117+ newfile("/dev/stderr")->F = stderr;
3118+
3119+ evaluate(beginseq.first, &G.main__tmpvar);
3120 if (!mainseq.first && !endseq.first)
3121- awk_exit(EXIT_SUCCESS);
3122+ awk_exit();
3123
3124 /* input file could already be opened in BEGIN block */
3125 if (!iF)
3126@@ -3347,7 +3695,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3127 nextrec = FALSE;
3128 incvar(intvar[NR]);
3129 incvar(intvar[FNR]);
3130- evaluate(mainseq.first, &tv);
3131+ evaluate(mainseq.first, &G.main__tmpvar);
3132
3133 if (nextfile)
3134 break;
3135@@ -3359,6 +3707,6 @@ int awk_main(int argc UNUSED_PARAM, char **argv)
3136 iF = next_input_file();
3137 }
3138
3139- awk_exit(EXIT_SUCCESS);
3140+ awk_exit();
3141 /*return 0;*/
3142 }
3143diff --git a/testsuite/awk.tests b/testsuite/awk.tests
3144index 92c83d719..4a7a01245 100755
3145--- a/testsuite/awk.tests
3146+++ b/testsuite/awk.tests
3147@@ -44,6 +44,16 @@ testing "awk handles empty function f(arg){}" \
3148 "L1\n\nL2\n\n" \
3149 "" ""
3150
3151+prg='
3152+function empty_fun(){}
3153+END {empty_fun()
3154+ print "Ok"
3155+}'
3156+testing "awk handles empty function f(){}" \
3157+ "awk '$prg'" \
3158+ "Ok\n" \
3159+ "" ""
3160+
3161 prg='
3162 function outer_fun() {
3163 return 1
3164@@ -71,6 +81,23 @@ testing "awk properly handles undefined function" \
3165 "L1\n\nawk: cmd. line:5: Call to undefined function\n" \
3166 "" ""
3167
3168+prg='
3169+BEGIN {
3170+ v=1
3171+ a=2
3172+ print v (a)
3173+}'
3174+testing "awk 'v (a)' is not a function call, it is a concatenation" \
3175+ "awk '$prg' 2>&1" \
3176+ "12\n" \
3177+ "" ""
3178+
3179+prg='func f(){print"F"};func g(){print"G"};BEGIN{f(g(),g())}'
3180+testing "awk unused function args are evaluated" \
3181+ "awk '$prg' 2>&1" \
3182+ "G\nG\nF\n" \
3183+ "" ""
3184+
3185
3186 optional DESKTOP
3187 testing "awk hex const 1" "awk '{ print or(0xffffffff,1) }'" "4294967295\n" "" "\n"
3188@@ -352,19 +379,14 @@ testing "awk -e and ARGC" \
3189 ""
3190 SKIP=
3191
3192-# The examples are in fact not valid awk programs (break/continue
3193-# can only be used inside loops).
3194-# But we do accept them outside of loops.
3195-# We had a bug with misparsing "break ; else" sequence.
3196-# Test that *that* bug is fixed, using simplest possible scripts:
3197 testing "awk break" \
3198 "awk -f - 2>&1; echo \$?" \
3199- "0\n" \
3200+ "awk: -:1: 'break' not in a loop\n1\n" \
3201 "" \
3202 'BEGIN { if (1) break; else a = 1 }'
3203 testing "awk continue" \
3204 "awk -f - 2>&1; echo \$?" \
3205- "0\n" \
3206+ "awk: -:1: 'continue' not in a loop\n1\n" \
3207 "" \
3208 'BEGIN { if (1) continue; else a = 1 }'
3209
3210@@ -383,6 +405,11 @@ testing "awk errors on missing delete arg" \
3211 "awk -e '{delete}' 2>&1" "awk: cmd. line:1: Too few arguments\n" "" ""
3212 SKIP=
3213
3214+optional FEATURE_AWK_GNU_EXTENSIONS
3215+testing "awk printf('%c') can output NUL" \
3216+ "awk '{printf(\"hello%c null\n\", 0)}'" "hello\0 null\n" "" "\n"
3217+SKIP=
3218+
3219 # testing "description" "command" "result" "infile" "stdin"
3220 testing 'awk negative field access' \
3221 'awk 2>&1 -- '\''{ $(-1) }'\' \
3222@@ -413,4 +440,25 @@ testing 'awk $NF is empty' \
3223 '' \
3224 'a=====123='
3225
3226+testing "awk exit N propagates through END's exit" \
3227+ "awk 'BEGIN { exit 42 } END { exit }'; echo \$?" \
3228+ "42\n" \
3229+ '' ''
3230+
3231+testing "awk print + redirect" \
3232+ "awk 'BEGIN { print \"STDERR %s\" >\"/dev/stderr\" }' 2>&1" \
3233+ "STDERR %s\n" \
3234+ '' ''
3235+
3236+testing "awk \"cmd\" | getline" \
3237+ "awk 'BEGIN { \"echo HELLO\" | getline; print }'" \
3238+ "HELLO\n" \
3239+ '' ''
3240+
3241+# printf %% should print one % (had a bug where it didn't)
3242+testing 'awk printf %% prints one %' \
3243+ "awk 'BEGIN { printf \"%%\n\" }'" \
3244+ "%\n" \
3245+ '' ''
3246+
3247 exit $FAILCOUNT
3248diff --git a/testsuite/printf.tests b/testsuite/printf.tests
3249index 34a65926e..050edef71 100755
3250--- a/testsuite/printf.tests
3251+++ b/testsuite/printf.tests
3252@@ -79,6 +79,11 @@ testing "printf understands %Ld" \
3253 "-5\n""0\n" \
3254 "" ""
3255
3256+testing "printf understands %%" \
3257+ "${bb}printf '%%\n' 2>&1; echo \$?" \
3258+ "%\n""0\n" \
3259+ "" ""
3260+
3261 testing "printf handles positive numbers for %d" \
3262 "${bb}printf '%d\n' 3 +3 ' 3' ' +3' 2>&1; echo \$?" \
3263 "3\n"\
3264--
32652.33.0
3266
diff --git a/meta/recipes-core/busybox/busybox/0002-man-fix-segfault-in-man-1.patch b/meta/recipes-core/busybox/busybox/0002-man-fix-segfault-in-man-1.patch
new file mode 100644
index 0000000000..4a930b7b6f
--- /dev/null
+++ b/meta/recipes-core/busybox/busybox/0002-man-fix-segfault-in-man-1.patch
@@ -0,0 +1,30 @@
1From 4975cace9bf96bfde174f8bb5cc4068d2ea294d4 Mon Sep 17 00:00:00 2001
2From: Denys Vlasenko <vda.linux@googlemail.com>
3Date: Tue, 15 Jun 2021 14:47:46 +0200
4Subject: [PATCH] man: fix segfault in "man 1"
5
6function old new delta
7man_main 942 954 +12
8
9Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
10
11Upstream-Status: Backport [4d4fc5ca5ee4f]
12CVE: CVE-2021-42373
13Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
14---
15 miscutils/man.c | 2 +-
16 1 file changed, 1 insertion(+), 1 deletion(-)
17
18diff --git a/miscutils/man.c b/miscutils/man.c
19index 722f6641e..d319e8bba 100644
20--- a/miscutils/man.c
21+++ b/miscutils/man.c
22@@ -324,7 +324,7 @@ int man_main(int argc UNUSED_PARAM, char **argv)
23
24 /* is 1st ARG a SECTION? */
25 sec_list = conf_sec_list;
26- if (is_section_name(conf_sec_list, *argv)) {
27+ if (is_section_name(conf_sec_list, *argv) && argv[1]) {
28 /* yes */
29 sec_list = *argv++;
30 }
diff --git a/meta/recipes-core/busybox/busybox_1.33.1.bb b/meta/recipes-core/busybox/busybox_1.33.2.bb
index 4002d6a5c6..4a0d3b4556 100644
--- a/meta/recipes-core/busybox/busybox_1.33.1.bb
+++ b/meta/recipes-core/busybox/busybox_1.33.2.bb
@@ -48,7 +48,9 @@ SRC_URI = "https://busybox.net/downloads/busybox-${PV}.tar.bz2;name=tarball \
48 file://0001-sysctl-ignore-EIO-of-stable_secret-below-proc-sys-ne.patch \ 48 file://0001-sysctl-ignore-EIO-of-stable_secret-below-proc-sys-ne.patch \
49 file://0001-gen_build_files-Use-C-locale-when-calling-sed-on-glo.patch \ 49 file://0001-gen_build_files-Use-C-locale-when-calling-sed-on-glo.patch \
50 file://0001-mktemp-add-tmpdir-option.patch \ 50 file://0001-mktemp-add-tmpdir-option.patch \
51 file://0001-awk-fix-CVEs.patch \
52 file://0002-man-fix-segfault-in-man-1.patch \
51 " 53 "
52SRC_URI_append_libc-musl = " file://musl.cfg " 54SRC_URI_append_libc-musl = " file://musl.cfg "
53 55
54SRC_URI[tarball.sha256sum] = "12cec6bd2b16d8a9446dd16130f2b92982f1819f6e1c5f5887b6db03f5660d28" 56SRC_URI[tarball.sha256sum] = "6843ba7977081e735fa0fdb05893e3c002c8c5ad7c9c80da206e603cc0ac47e7"
diff --git a/meta/recipes-core/expat/expat/CVE-2021-45960.patch b/meta/recipes-core/expat/expat/CVE-2021-45960.patch
new file mode 100644
index 0000000000..523449e22c
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2021-45960.patch
@@ -0,0 +1,65 @@
1From 0adcb34c49bee5b19bd29b16a578c510c23597ea Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Mon, 27 Dec 2021 20:15:02 +0100
4Subject: [PATCH] lib: Detect and prevent troublesome left shifts in function
5 storeAtts (CVE-2021-45960)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/pull/534/commits/0adcb34c49bee5b19bd29b16a578c510c23597ea
9
10CVE: CVE-2021-45960
11Signed-off-by: Steve Sakoman <steve@sakoman.com>
12
13---
14 expat/lib/xmlparse.c | 31 +++++++++++++++++++++++++++++--
15 1 file changed, 29 insertions(+), 2 deletions(-)
16
17diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
18index d730f41c3..b47c31b05 100644
19--- a/lib/xmlparse.c
20+++ b/lib/xmlparse.c
21@@ -3414,7 +3414,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
22 if (nPrefixes) {
23 int j; /* hash table index */
24 unsigned long version = parser->m_nsAttsVersion;
25- int nsAttsSize = (int)1 << parser->m_nsAttsPower;
26+
27+ /* Detect and prevent invalid shift */
28+ if (parser->m_nsAttsPower >= sizeof(unsigned int) * 8 /* bits per byte */) {
29+ return XML_ERROR_NO_MEMORY;
30+ }
31+
32+ unsigned int nsAttsSize = 1u << parser->m_nsAttsPower;
33 unsigned char oldNsAttsPower = parser->m_nsAttsPower;
34 /* size of hash table must be at least 2 * (# of prefixed attributes) */
35 if ((nPrefixes << 1)
36@@ -3425,7 +3431,28 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
37 ;
38 if (parser->m_nsAttsPower < 3)
39 parser->m_nsAttsPower = 3;
40- nsAttsSize = (int)1 << parser->m_nsAttsPower;
41+
42+ /* Detect and prevent invalid shift */
43+ if (parser->m_nsAttsPower >= sizeof(nsAttsSize) * 8 /* bits per byte */) {
44+ /* Restore actual size of memory in m_nsAtts */
45+ parser->m_nsAttsPower = oldNsAttsPower;
46+ return XML_ERROR_NO_MEMORY;
47+ }
48+
49+ nsAttsSize = 1u << parser->m_nsAttsPower;
50+
51+ /* Detect and prevent integer overflow.
52+ * The preprocessor guard addresses the "always false" warning
53+ * from -Wtype-limits on platforms where
54+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
55+#if UINT_MAX >= SIZE_MAX
56+ if (nsAttsSize > (size_t)(-1) / sizeof(NS_ATT)) {
57+ /* Restore actual size of memory in m_nsAtts */
58+ parser->m_nsAttsPower = oldNsAttsPower;
59+ return XML_ERROR_NO_MEMORY;
60+ }
61+#endif
62+
63 temp = (NS_ATT *)REALLOC(parser, parser->m_nsAtts,
64 nsAttsSize * sizeof(NS_ATT));
65 if (! temp) {
diff --git a/meta/recipes-core/expat/expat/CVE-2021-46143.patch b/meta/recipes-core/expat/expat/CVE-2021-46143.patch
new file mode 100644
index 0000000000..b1a726d9a8
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2021-46143.patch
@@ -0,0 +1,49 @@
1From 85ae9a2d7d0e9358f356b33977b842df8ebaec2b Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Sat, 25 Dec 2021 20:52:08 +0100
4Subject: [PATCH] lib: Prevent integer overflow on m_groupSize in function
5 doProlog (CVE-2021-46143)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/pull/538/commits/85ae9a2d7d0e9358f356b33977b842df8ebaec2b
9
10CVE: CVE-2021-46143
11
12Signed-off-by: Steve Sakoman <steve@sakoman.com>
13---
14 expat/lib/xmlparse.c | 15 +++++++++++++++
15 1 file changed, 15 insertions(+)
16
17diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
18index b47c31b0..8f243126 100644
19--- a/lib/xmlparse.c
20+++ b/lib/xmlparse.c
21@@ -5046,6 +5046,11 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
22 if (parser->m_prologState.level >= parser->m_groupSize) {
23 if (parser->m_groupSize) {
24 {
25+ /* Detect and prevent integer overflow */
26+ if (parser->m_groupSize > (unsigned int)(-1) / 2u) {
27+ return XML_ERROR_NO_MEMORY;
28+ }
29+
30 char *const new_connector = (char *)REALLOC(
31 parser, parser->m_groupConnector, parser->m_groupSize *= 2);
32 if (new_connector == NULL) {
33@@ -5056,6 +5061,16 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
34 }
35
36 if (dtd->scaffIndex) {
37+ /* Detect and prevent integer overflow.
38+ * The preprocessor guard addresses the "always false" warning
39+ * from -Wtype-limits on platforms where
40+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
41+#if UINT_MAX >= SIZE_MAX
42+ if (parser->m_groupSize > (size_t)(-1) / sizeof(int)) {
43+ return XML_ERROR_NO_MEMORY;
44+ }
45+#endif
46+
47 int *const new_scaff_index = (int *)REALLOC(
48 parser, dtd->scaffIndex, parser->m_groupSize * sizeof(int));
49 if (new_scaff_index == NULL)
diff --git a/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch
new file mode 100644
index 0000000000..e569fbc7ab
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-22822-27.patch
@@ -0,0 +1,257 @@
1From 9f93e8036e842329863bf20395b8fb8f73834d9e Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Thu, 30 Dec 2021 22:46:03 +0100
4Subject: [PATCH] lib: Prevent integer overflow at multiple places
5 (CVE-2022-22822 to CVE-2022-22827)
6
7The involved functions are:
8- addBinding (CVE-2022-22822)
9- build_model (CVE-2022-22823)
10- defineAttribute (CVE-2022-22824)
11- lookup (CVE-2022-22825)
12- nextScaffoldPart (CVE-2022-22826)
13- storeAtts (CVE-2022-22827)
14
15Upstream-Status: Backport:
16https://github.com/libexpat/libexpat/pull/539/commits/9f93e8036e842329863bf20395b8fb8f73834d9e
17
18CVE: CVE-2022-22822 CVE-2022-22823 CVE-2022-22824 CVE-2022-22825 CVE-2022-22826 CVE-2022-22827
19Signed-off-by: Steve Sakoman <steve@sakoman.com>
20
21---
22 expat/lib/xmlparse.c | 153 ++++++++++++++++++++++++++++++++++++++++++-
23 1 file changed, 151 insertions(+), 2 deletions(-)
24
25diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
26index 8f243126..575e73ee 100644
27--- a/lib/xmlparse.c
28+++ b/lib/xmlparse.c
29@@ -3261,13 +3261,38 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
30
31 /* get the attributes from the tokenizer */
32 n = XmlGetAttributes(enc, attStr, parser->m_attsSize, parser->m_atts);
33+
34+ /* Detect and prevent integer overflow */
35+ if (n > INT_MAX - nDefaultAtts) {
36+ return XML_ERROR_NO_MEMORY;
37+ }
38+
39 if (n + nDefaultAtts > parser->m_attsSize) {
40 int oldAttsSize = parser->m_attsSize;
41 ATTRIBUTE *temp;
42 #ifdef XML_ATTR_INFO
43 XML_AttrInfo *temp2;
44 #endif
45+
46+ /* Detect and prevent integer overflow */
47+ if ((nDefaultAtts > INT_MAX - INIT_ATTS_SIZE)
48+ || (n > INT_MAX - (nDefaultAtts + INIT_ATTS_SIZE))) {
49+ return XML_ERROR_NO_MEMORY;
50+ }
51+
52 parser->m_attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
53+
54+ /* Detect and prevent integer overflow.
55+ * The preprocessor guard addresses the "always false" warning
56+ * from -Wtype-limits on platforms where
57+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
58+#if UINT_MAX >= SIZE_MAX
59+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(ATTRIBUTE)) {
60+ parser->m_attsSize = oldAttsSize;
61+ return XML_ERROR_NO_MEMORY;
62+ }
63+#endif
64+
65 temp = (ATTRIBUTE *)REALLOC(parser, (void *)parser->m_atts,
66 parser->m_attsSize * sizeof(ATTRIBUTE));
67 if (temp == NULL) {
68@@ -3276,6 +3301,17 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
69 }
70 parser->m_atts = temp;
71 #ifdef XML_ATTR_INFO
72+ /* Detect and prevent integer overflow.
73+ * The preprocessor guard addresses the "always false" warning
74+ * from -Wtype-limits on platforms where
75+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
76+# if UINT_MAX >= SIZE_MAX
77+ if ((unsigned)parser->m_attsSize > (size_t)(-1) / sizeof(XML_AttrInfo)) {
78+ parser->m_attsSize = oldAttsSize;
79+ return XML_ERROR_NO_MEMORY;
80+ }
81+# endif
82+
83 temp2 = (XML_AttrInfo *)REALLOC(parser, (void *)parser->m_attInfo,
84 parser->m_attsSize * sizeof(XML_AttrInfo));
85 if (temp2 == NULL) {
86@@ -3610,9 +3646,31 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
87 tagNamePtr->prefixLen = prefixLen;
88 for (i = 0; localPart[i++];)
89 ; /* i includes null terminator */
90+
91+ /* Detect and prevent integer overflow */
92+ if (binding->uriLen > INT_MAX - prefixLen
93+ || i > INT_MAX - (binding->uriLen + prefixLen)) {
94+ return XML_ERROR_NO_MEMORY;
95+ }
96+
97 n = i + binding->uriLen + prefixLen;
98 if (n > binding->uriAlloc) {
99 TAG *p;
100+
101+ /* Detect and prevent integer overflow */
102+ if (n > INT_MAX - EXPAND_SPARE) {
103+ return XML_ERROR_NO_MEMORY;
104+ }
105+ /* Detect and prevent integer overflow.
106+ * The preprocessor guard addresses the "always false" warning
107+ * from -Wtype-limits on platforms where
108+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
109+#if UINT_MAX >= SIZE_MAX
110+ if ((unsigned)(n + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
111+ return XML_ERROR_NO_MEMORY;
112+ }
113+#endif
114+
115 uri = (XML_Char *)MALLOC(parser, (n + EXPAND_SPARE) * sizeof(XML_Char));
116 if (! uri)
117 return XML_ERROR_NO_MEMORY;
118@@ -3708,6 +3766,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
119 if (parser->m_freeBindingList) {
120 b = parser->m_freeBindingList;
121 if (len > b->uriAlloc) {
122+ /* Detect and prevent integer overflow */
123+ if (len > INT_MAX - EXPAND_SPARE) {
124+ return XML_ERROR_NO_MEMORY;
125+ }
126+
127+ /* Detect and prevent integer overflow.
128+ * The preprocessor guard addresses the "always false" warning
129+ * from -Wtype-limits on platforms where
130+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
131+#if UINT_MAX >= SIZE_MAX
132+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
133+ return XML_ERROR_NO_MEMORY;
134+ }
135+#endif
136+
137 XML_Char *temp = (XML_Char *)REALLOC(
138 parser, b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
139 if (temp == NULL)
140@@ -3720,6 +3793,21 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
141 b = (BINDING *)MALLOC(parser, sizeof(BINDING));
142 if (! b)
143 return XML_ERROR_NO_MEMORY;
144+
145+ /* Detect and prevent integer overflow */
146+ if (len > INT_MAX - EXPAND_SPARE) {
147+ return XML_ERROR_NO_MEMORY;
148+ }
149+ /* Detect and prevent integer overflow.
150+ * The preprocessor guard addresses the "always false" warning
151+ * from -Wtype-limits on platforms where
152+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
153+#if UINT_MAX >= SIZE_MAX
154+ if ((unsigned)(len + EXPAND_SPARE) > (size_t)(-1) / sizeof(XML_Char)) {
155+ return XML_ERROR_NO_MEMORY;
156+ }
157+#endif
158+
159 b->uri
160 = (XML_Char *)MALLOC(parser, sizeof(XML_Char) * (len + EXPAND_SPARE));
161 if (! b->uri) {
162@@ -6141,7 +6229,24 @@ defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, XML_Bool isCdata,
163 }
164 } else {
165 DEFAULT_ATTRIBUTE *temp;
166+
167+ /* Detect and prevent integer overflow */
168+ if (type->allocDefaultAtts > INT_MAX / 2) {
169+ return 0;
170+ }
171+
172 int count = type->allocDefaultAtts * 2;
173+
174+ /* Detect and prevent integer overflow.
175+ * The preprocessor guard addresses the "always false" warning
176+ * from -Wtype-limits on platforms where
177+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
178+#if UINT_MAX >= SIZE_MAX
179+ if ((unsigned)count > (size_t)(-1) / sizeof(DEFAULT_ATTRIBUTE)) {
180+ return 0;
181+ }
182+#endif
183+
184 temp = (DEFAULT_ATTRIBUTE *)REALLOC(parser, type->defaultAtts,
185 (count * sizeof(DEFAULT_ATTRIBUTE)));
186 if (temp == NULL)
187@@ -6792,8 +6897,20 @@ lookup(XML_Parser parser, HASH_TABLE *table, KEY name, size_t createSize) {
188 /* check for overflow (table is half full) */
189 if (table->used >> (table->power - 1)) {
190 unsigned char newPower = table->power + 1;
191+
192+ /* Detect and prevent invalid shift */
193+ if (newPower >= sizeof(unsigned long) * 8 /* bits per byte */) {
194+ return NULL;
195+ }
196+
197 size_t newSize = (size_t)1 << newPower;
198 unsigned long newMask = (unsigned long)newSize - 1;
199+
200+ /* Detect and prevent integer overflow */
201+ if (newSize > (size_t)(-1) / sizeof(NAMED *)) {
202+ return NULL;
203+ }
204+
205 size_t tsize = newSize * sizeof(NAMED *);
206 NAMED **newV = (NAMED **)table->mem->malloc_fcn(tsize);
207 if (! newV)
208@@ -7143,6 +7260,20 @@ nextScaffoldPart(XML_Parser parser) {
209 if (dtd->scaffCount >= dtd->scaffSize) {
210 CONTENT_SCAFFOLD *temp;
211 if (dtd->scaffold) {
212+ /* Detect and prevent integer overflow */
213+ if (dtd->scaffSize > UINT_MAX / 2u) {
214+ return -1;
215+ }
216+ /* Detect and prevent integer overflow.
217+ * The preprocessor guard addresses the "always false" warning
218+ * from -Wtype-limits on platforms where
219+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
220+#if UINT_MAX >= SIZE_MAX
221+ if (dtd->scaffSize > (size_t)(-1) / 2u / sizeof(CONTENT_SCAFFOLD)) {
222+ return -1;
223+ }
224+#endif
225+
226 temp = (CONTENT_SCAFFOLD *)REALLOC(
227 parser, dtd->scaffold, dtd->scaffSize * 2 * sizeof(CONTENT_SCAFFOLD));
228 if (temp == NULL)
229@@ -7212,8 +7343,26 @@ build_model(XML_Parser parser) {
230 XML_Content *ret;
231 XML_Content *cpos;
232 XML_Char *str;
233- int allocsize = (dtd->scaffCount * sizeof(XML_Content)
234- + (dtd->contentStringLen * sizeof(XML_Char)));
235+
236+ /* Detect and prevent integer overflow.
237+ * The preprocessor guard addresses the "always false" warning
238+ * from -Wtype-limits on platforms where
239+ * sizeof(unsigned int) < sizeof(size_t), e.g. on x86_64. */
240+#if UINT_MAX >= SIZE_MAX
241+ if (dtd->scaffCount > (size_t)(-1) / sizeof(XML_Content)) {
242+ return NULL;
243+ }
244+ if (dtd->contentStringLen > (size_t)(-1) / sizeof(XML_Char)) {
245+ return NULL;
246+ }
247+#endif
248+ if (dtd->scaffCount * sizeof(XML_Content)
249+ > (size_t)(-1) - dtd->contentStringLen * sizeof(XML_Char)) {
250+ return NULL;
251+ }
252+
253+ const size_t allocsize = (dtd->scaffCount * sizeof(XML_Content)
254+ + (dtd->contentStringLen * sizeof(XML_Char)));
255
256 ret = (XML_Content *)MALLOC(parser, allocsize);
257 if (! ret)
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23852.patch b/meta/recipes-core/expat/expat/CVE-2022-23852.patch
new file mode 100644
index 0000000000..41425c108b
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-23852.patch
@@ -0,0 +1,33 @@
1From 847a645152f5ebc10ac63b74b604d0c1a79fae40 Mon Sep 17 00:00:00 2001
2From: Samanta Navarro <ferivoz@riseup.net>
3Date: Sat, 22 Jan 2022 17:48:00 +0100
4Subject: [PATCH] lib: Detect and prevent integer overflow in XML_GetBuffer
5 (CVE-2022-23852)
6
7Upstream-Status: Backport:
8https://github.com/libexpat/libexpat/commit/847a645152f5ebc10ac63b74b604d0c1a79fae40
9
10CVE: CVE-2022-23852
11
12Signed-off-by: Steve Sakoman <steve@sakoman.com>
13
14---
15 expat/lib/xmlparse.c | 5 +++++
16 1 file changed, 5 insertions(+)
17
18diff --git a/expat/lib/xmlparse.c b/expat/lib/xmlparse.c
19index d54af683..5ce31402 100644
20--- a/lib/xmlparse.c
21+++ b/lib/xmlparse.c
22@@ -2067,6 +2067,11 @@ XML_GetBuffer(XML_Parser parser, int len) {
23 keep = (int)EXPAT_SAFE_PTR_DIFF(parser->m_bufferPtr, parser->m_buffer);
24 if (keep > XML_CONTEXT_BYTES)
25 keep = XML_CONTEXT_BYTES;
26+ /* Detect and prevent integer overflow */
27+ if (keep > INT_MAX - neededSize) {
28+ parser->m_errorCode = XML_ERROR_NO_MEMORY;
29+ return NULL;
30+ }
31 neededSize += keep;
32 #endif /* defined XML_CONTEXT_BYTES */
33 if (neededSize
diff --git a/meta/recipes-core/expat/expat/CVE-2022-23990.patch b/meta/recipes-core/expat/expat/CVE-2022-23990.patch
new file mode 100644
index 0000000000..c599517b3e
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-23990.patch
@@ -0,0 +1,49 @@
1From ede41d1e186ed2aba88a06e84cac839b770af3a1 Mon Sep 17 00:00:00 2001
2From: Sebastian Pipping <sebastian@pipping.org>
3Date: Wed, 26 Jan 2022 02:36:43 +0100
4Subject: [PATCH] lib: Prevent integer overflow in doProlog (CVE-2022-23990)
5
6The change from "int nameLen" to "size_t nameLen"
7addresses the overflow on "nameLen++" in code
8"for (; name[nameLen++];)" right above the second
9change in the patch.
10
11Upstream-Status: Backport:
12https://github.com/libexpat/libexpat/pull/551/commits/ede41d1e186ed2aba88a06e84cac839b770af3a1
13
14CVE: CVE-2022-23990
15
16Signed-off-by: Steve Sakoman <steve@sakoman.com>
17
18---
19 lib/xmlparse.c | 10 ++++++++--
20 1 file changed, 8 insertions(+), 2 deletions(-)
21
22diff --git a/lib/xmlparse.c b/expat/lib/xmlparse.c
23index 5ce31402..d1d17005 100644
24--- a/lib/xmlparse.c
25+++ b/lib/xmlparse.c
26@@ -5372,7 +5372,7 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
27 if (dtd->in_eldecl) {
28 ELEMENT_TYPE *el;
29 const XML_Char *name;
30- int nameLen;
31+ size_t nameLen;
32 const char *nxt
33 = (quant == XML_CQUANT_NONE ? next : next - enc->minBytesPerChar);
34 int myindex = nextScaffoldPart(parser);
35@@ -5388,7 +5388,13 @@ doProlog(XML_Parser parser, const ENCODING *enc, const char *s, const char *end,
36 nameLen = 0;
37 for (; name[nameLen++];)
38 ;
39- dtd->contentStringLen += nameLen;
40+
41+ /* Detect and prevent integer overflow */
42+ if (nameLen > UINT_MAX - dtd->contentStringLen) {
43+ return XML_ERROR_NO_MEMORY;
44+ }
45+
46+ dtd->contentStringLen += (unsigned)nameLen;
47 if (parser->m_elementDeclHandler)
48 handleDefault = XML_FALSE;
49 }
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25235.patch b/meta/recipes-core/expat/expat/CVE-2022-25235.patch
new file mode 100644
index 0000000000..9febeae609
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25235.patch
@@ -0,0 +1,261 @@
1Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/306b721]
2CVE: CVE-2022-25235
3
4The commit is a merge commit, and this patch is created by:
5
6$ git show -m -p --stat 306b72134f157bbfd1637b20a22cabf4acfa136a
7
8Remove modification for expat/Changes which fails to be applied.
9
10Signed-off-by: Kai Kang <kai.kang@windriver.com>
11
12commit 306b72134f157bbfd1637b20a22cabf4acfa136a (from 2cc97e875ef84da4bcf55156c83599116f7523b4)
13Merge: 2cc97e87 c16300f0
14Author: Sebastian Pipping <sebastian@pipping.org>
15Date: Fri Feb 18 20:12:32 2022 +0100
16
17 Merge pull request #562 from libexpat/utf8-security
18
19 [CVE-2022-25235] lib: Protect against malformed encoding (e.g. malformed UTF-8)
20---
21 expat/Changes | 7 ++++
22 expat/lib/xmltok.c | 5 ---
23 expat/lib/xmltok_impl.c | 18 ++++----
24 expat/tests/runtests.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++
25 4 files changed, 127 insertions(+), 12 deletions(-)
26
27diff --git a/lib/xmltok.c b/lib/xmltok.c
28index a72200e8..3bddf125 100644
29--- a/lib/xmltok.c
30+++ b/lib/xmltok.c
31@@ -98,11 +98,6 @@
32 + ((((byte)[1]) & 3) << 1) + ((((byte)[2]) >> 5) & 1)] \
33 & (1u << (((byte)[2]) & 0x1F)))
34
35-#define UTF8_GET_NAMING(pages, p, n) \
36- ((n) == 2 \
37- ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
38- : ((n) == 3 ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) : 0))
39-
40 /* Detection of invalid UTF-8 sequences is based on Table 3.1B
41 of Unicode 3.2: http://www.unicode.org/unicode/reports/tr28/
42 with the additional restriction of not allowing the Unicode
43diff --git a/lib/xmltok_impl.c b/lib/xmltok_impl.c
44index 0430591b..84ff35f9 100644
45--- a/lib/xmltok_impl.c
46+++ b/lib/xmltok_impl.c
47@@ -69,7 +69,7 @@
48 case BT_LEAD##n: \
49 if (end - ptr < n) \
50 return XML_TOK_PARTIAL_CHAR; \
51- if (! IS_NAME_CHAR(enc, ptr, n)) { \
52+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NAME_CHAR(enc, ptr, n)) { \
53 *nextTokPtr = ptr; \
54 return XML_TOK_INVALID; \
55 } \
56@@ -98,7 +98,7 @@
57 case BT_LEAD##n: \
58 if (end - ptr < n) \
59 return XML_TOK_PARTIAL_CHAR; \
60- if (! IS_NMSTRT_CHAR(enc, ptr, n)) { \
61+ if (IS_INVALID_CHAR(enc, ptr, n) || ! IS_NMSTRT_CHAR(enc, ptr, n)) { \
62 *nextTokPtr = ptr; \
63 return XML_TOK_INVALID; \
64 } \
65@@ -1142,6 +1142,10 @@ PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
66 case BT_LEAD##n: \
67 if (end - ptr < n) \
68 return XML_TOK_PARTIAL_CHAR; \
69+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
70+ *nextTokPtr = ptr; \
71+ return XML_TOK_INVALID; \
72+ } \
73 if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
74 ptr += n; \
75 tok = XML_TOK_NAME; \
76@@ -1270,7 +1274,7 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
77 switch (BYTE_TYPE(enc, ptr)) {
78 # define LEAD_CASE(n) \
79 case BT_LEAD##n: \
80- ptr += n; \
81+ ptr += n; /* NOTE: The encoding has already been validated. */ \
82 break;
83 LEAD_CASE(2)
84 LEAD_CASE(3)
85@@ -1339,7 +1343,7 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
86 switch (BYTE_TYPE(enc, ptr)) {
87 # define LEAD_CASE(n) \
88 case BT_LEAD##n: \
89- ptr += n; \
90+ ptr += n; /* NOTE: The encoding has already been validated. */ \
91 break;
92 LEAD_CASE(2)
93 LEAD_CASE(3)
94@@ -1518,7 +1522,7 @@ PREFIX(getAtts)(const ENCODING *enc, const char *ptr, int attsMax,
95 state = inName; \
96 }
97 # define LEAD_CASE(n) \
98- case BT_LEAD##n: \
99+ case BT_LEAD##n: /* NOTE: The encoding has already been validated. */ \
100 START_NAME ptr += (n - MINBPC(enc)); \
101 break;
102 LEAD_CASE(2)
103@@ -1730,7 +1734,7 @@ PREFIX(nameLength)(const ENCODING *enc, const char *ptr) {
104 switch (BYTE_TYPE(enc, ptr)) {
105 # define LEAD_CASE(n) \
106 case BT_LEAD##n: \
107- ptr += n; \
108+ ptr += n; /* NOTE: The encoding has already been validated. */ \
109 break;
110 LEAD_CASE(2)
111 LEAD_CASE(3)
112@@ -1775,7 +1779,7 @@ PREFIX(updatePosition)(const ENCODING *enc, const char *ptr, const char *end,
113 switch (BYTE_TYPE(enc, ptr)) {
114 # define LEAD_CASE(n) \
115 case BT_LEAD##n: \
116- ptr += n; \
117+ ptr += n; /* NOTE: The encoding has already been validated. */ \
118 pos->columnNumber++; \
119 break;
120 LEAD_CASE(2)
121diff --git a/tests/runtests.c b/tests/runtests.c
122index bc5344b1..9b155b82 100644
123--- a/tests/runtests.c
124+++ b/tests/runtests.c
125@@ -5998,6 +5998,105 @@ START_TEST(test_utf8_in_cdata_section_2) {
126 }
127 END_TEST
128
129+START_TEST(test_utf8_in_start_tags) {
130+ struct test_case {
131+ bool goodName;
132+ bool goodNameStart;
133+ const char *tagName;
134+ };
135+
136+ // The idea with the tests below is this:
137+ // We want to cover 1-, 2- and 3-byte sequences, 4-byte sequences
138+ // go to isNever and are hence not a concern.
139+ //
140+ // We start with a character that is a valid name character
141+ // (or even name-start character, see XML 1.0r4 spec) and then we flip
142+ // single bits at places where (1) the result leaves the UTF-8 encoding space
143+ // and (2) we stay in the same n-byte sequence family.
144+ //
145+ // The flipped bits are highlighted in angle brackets in comments,
146+ // e.g. "[<1>011 1001]" means we had [0011 1001] but we now flipped
147+ // the most significant bit to 1 to leave UTF-8 encoding space.
148+ struct test_case cases[] = {
149+ // 1-byte UTF-8: [0xxx xxxx]
150+ {true, true, "\x3A"}, // [0011 1010] = ASCII colon ':'
151+ {false, false, "\xBA"}, // [<1>011 1010]
152+ {true, false, "\x39"}, // [0011 1001] = ASCII nine '9'
153+ {false, false, "\xB9"}, // [<1>011 1001]
154+
155+ // 2-byte UTF-8: [110x xxxx] [10xx xxxx]
156+ {true, true, "\xDB\xA5"}, // [1101 1011] [1010 0101] =
157+ // Arabic small waw U+06E5
158+ {false, false, "\x9B\xA5"}, // [1<0>01 1011] [1010 0101]
159+ {false, false, "\xDB\x25"}, // [1101 1011] [<0>010 0101]
160+ {false, false, "\xDB\xE5"}, // [1101 1011] [1<1>10 0101]
161+ {true, false, "\xCC\x81"}, // [1100 1100] [1000 0001] =
162+ // combining char U+0301
163+ {false, false, "\x8C\x81"}, // [1<0>00 1100] [1000 0001]
164+ {false, false, "\xCC\x01"}, // [1100 1100] [<0>000 0001]
165+ {false, false, "\xCC\xC1"}, // [1100 1100] [1<1>00 0001]
166+
167+ // 3-byte UTF-8: [1110 xxxx] [10xx xxxx] [10xxxxxx]
168+ {true, true, "\xE0\xA4\x85"}, // [1110 0000] [1010 0100] [1000 0101] =
169+ // Devanagari Letter A U+0905
170+ {false, false, "\xA0\xA4\x85"}, // [1<0>10 0000] [1010 0100] [1000 0101]
171+ {false, false, "\xE0\x24\x85"}, // [1110 0000] [<0>010 0100] [1000 0101]
172+ {false, false, "\xE0\xE4\x85"}, // [1110 0000] [1<1>10 0100] [1000 0101]
173+ {false, false, "\xE0\xA4\x05"}, // [1110 0000] [1010 0100] [<0>000 0101]
174+ {false, false, "\xE0\xA4\xC5"}, // [1110 0000] [1010 0100] [1<1>00 0101]
175+ {true, false, "\xE0\xA4\x81"}, // [1110 0000] [1010 0100] [1000 0001] =
176+ // combining char U+0901
177+ {false, false, "\xA0\xA4\x81"}, // [1<0>10 0000] [1010 0100] [1000 0001]
178+ {false, false, "\xE0\x24\x81"}, // [1110 0000] [<0>010 0100] [1000 0001]
179+ {false, false, "\xE0\xE4\x81"}, // [1110 0000] [1<1>10 0100] [1000 0001]
180+ {false, false, "\xE0\xA4\x01"}, // [1110 0000] [1010 0100] [<0>000 0001]
181+ {false, false, "\xE0\xA4\xC1"}, // [1110 0000] [1010 0100] [1<1>00 0001]
182+ };
183+ const bool atNameStart[] = {true, false};
184+
185+ size_t i = 0;
186+ char doc[1024];
187+ size_t failCount = 0;
188+
189+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
190+ size_t j = 0;
191+ for (; j < sizeof(atNameStart) / sizeof(atNameStart[0]); j++) {
192+ const bool expectedSuccess
193+ = atNameStart[j] ? cases[i].goodNameStart : cases[i].goodName;
194+ sprintf(doc, "<%s%s><!--", atNameStart[j] ? "" : "a", cases[i].tagName);
195+ XML_Parser parser = XML_ParserCreate(NULL);
196+
197+ const enum XML_Status status
198+ = XML_Parse(parser, doc, (int)strlen(doc), /*isFinal=*/XML_FALSE);
199+
200+ bool success = true;
201+ if ((status == XML_STATUS_OK) != expectedSuccess) {
202+ success = false;
203+ }
204+ if ((status == XML_STATUS_ERROR)
205+ && (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)) {
206+ success = false;
207+ }
208+
209+ if (! success) {
210+ fprintf(
211+ stderr,
212+ "FAIL case %2u (%sat name start, %u-byte sequence, error code %d)\n",
213+ (unsigned)i + 1u, atNameStart[j] ? " " : "not ",
214+ (unsigned)strlen(cases[i].tagName), XML_GetErrorCode(parser));
215+ failCount++;
216+ }
217+
218+ XML_ParserFree(parser);
219+ }
220+ }
221+
222+ if (failCount > 0) {
223+ fail("UTF-8 regression detected");
224+ }
225+}
226+END_TEST
227+
228 /* Test trailing spaces in elements are accepted */
229 static void XMLCALL
230 record_element_end_handler(void *userData, const XML_Char *name) {
231@@ -6175,6 +6274,14 @@ START_TEST(test_bad_doctype) {
232 }
233 END_TEST
234
235+START_TEST(test_bad_doctype_utf8) {
236+ const char *text = "<!DOCTYPE \xDB\x25"
237+ "doc><doc/>"; // [1101 1011] [<0>010 0101]
238+ expect_failure(text, XML_ERROR_INVALID_TOKEN,
239+ "Invalid UTF-8 in DOCTYPE not faulted");
240+}
241+END_TEST
242+
243 START_TEST(test_bad_doctype_utf16) {
244 const char text[] =
245 /* <!DOCTYPE doc [ \x06f2 ]><doc/>
246@@ -11870,6 +11977,7 @@ make_suite(void) {
247 tcase_add_test(tc_basic, test_ext_entity_utf8_non_bom);
248 tcase_add_test(tc_basic, test_utf8_in_cdata_section);
249 tcase_add_test(tc_basic, test_utf8_in_cdata_section_2);
250+ tcase_add_test(tc_basic, test_utf8_in_start_tags);
251 tcase_add_test(tc_basic, test_trailing_spaces_in_elements);
252 tcase_add_test(tc_basic, test_utf16_attribute);
253 tcase_add_test(tc_basic, test_utf16_second_attr);
254@@ -11878,6 +11986,7 @@ make_suite(void) {
255 tcase_add_test(tc_basic, test_bad_attr_desc_keyword);
256 tcase_add_test(tc_basic, test_bad_attr_desc_keyword_utf16);
257 tcase_add_test(tc_basic, test_bad_doctype);
258+ tcase_add_test(tc_basic, test_bad_doctype_utf8);
259 tcase_add_test(tc_basic, test_bad_doctype_utf16);
260 tcase_add_test(tc_basic, test_bad_doctype_plus);
261 tcase_add_test(tc_basic, test_bad_doctype_star);
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch
new file mode 100644
index 0000000000..ab53d99c8f
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25236-1.patch
@@ -0,0 +1,116 @@
1Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/2cc97e87]
2CVE: CVE-2022-25236
3
4The commit is a merge commit, and this patch is created by:
5
6$ git diff -p --stat 2cc97e87~ 2cc97e87
7
8Remove modification for expat/Changes which fails to be applied.
9
10Signed-off-by: Kai Kang <kai.kang@windriver.com>
11
12commit 2cc97e875ef84da4bcf55156c83599116f7523b4 (from d477fdd284468f2ab822024e75702f2c1b254f42)
13Merge: d477fdd2 e4d7e497
14Author: Sebastian Pipping <sebastian@pipping.org>
15Date: Fri Feb 18 18:01:27 2022 +0100
16
17 Merge pull request #561 from libexpat/namesep-security
18
19 [CVE-2022-25236] lib: Protect against insertion of namesep characters into namespace URIs
20
21---
22 expat/Changes | 16 ++++++++++++++++
23 expat/lib/xmlparse.c | 17 +++++++++++++----
24 expat/tests/runtests.c | 30 ++++++++++++++++++++++++++++++
25 3 files changed, 59 insertions(+), 4 deletions(-)
26
27diff --git a/lib/xmlparse.c b/lib/xmlparse.c
28index 7376aab1..c98e2e9f 100644
29--- a/lib/xmlparse.c
30+++ b/lib/xmlparse.c
31@@ -718,8 +718,7 @@ XML_ParserCreate(const XML_Char *encodingName) {
32
33 XML_Parser XMLCALL
34 XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep) {
35- XML_Char tmp[2];
36- *tmp = nsSep;
37+ XML_Char tmp[2] = {nsSep, 0};
38 return XML_ParserCreate_MM(encodingName, NULL, tmp);
39 }
40
41@@ -1344,8 +1343,7 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser, const XML_Char *context,
42 would be otherwise.
43 */
44 if (parser->m_ns) {
45- XML_Char tmp[2];
46- *tmp = parser->m_namespaceSeparator;
47+ XML_Char tmp[2] = {parser->m_namespaceSeparator, 0};
48 parser = parserCreate(encodingName, &parser->m_mem, tmp, newDtd);
49 } else {
50 parser = parserCreate(encodingName, &parser->m_mem, NULL, newDtd);
51@@ -3761,6 +3759,17 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
52 if (! mustBeXML && isXMLNS
53 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
54 isXMLNS = XML_FALSE;
55+
56+ // NOTE: While Expat does not validate namespace URIs against RFC 3986,
57+ // we have to at least make sure that the XML processor on top of
58+ // Expat (that is splitting tag names by namespace separator into
59+ // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
60+ // by an attacker putting additional namespace separator characters
61+ // into namespace declarations. That would be ambiguous and not to
62+ // be expected.
63+ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
64+ return XML_ERROR_SYNTAX;
65+ }
66 }
67 isXML = isXML && len == xmlLen;
68 isXMLNS = isXMLNS && len == xmlnsLen;
69diff --git a/tests/runtests.c b/tests/runtests.c
70index d07203f2..bc5344b1 100644
71--- a/tests/runtests.c
72+++ b/tests/runtests.c
73@@ -7220,6 +7220,35 @@ START_TEST(test_ns_double_colon_doctype) {
74 }
75 END_TEST
76
77+START_TEST(test_ns_separator_in_uri) {
78+ struct test_case {
79+ enum XML_Status expectedStatus;
80+ const char *doc;
81+ };
82+ struct test_case cases[] = {
83+ {XML_STATUS_OK, "<doc xmlns='one_two' />"},
84+ {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
85+ };
86+
87+ size_t i = 0;
88+ size_t failCount = 0;
89+ for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
90+ XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
91+ XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
92+ if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
93+ /*isFinal*/ XML_TRUE)
94+ != cases[i].expectedStatus) {
95+ failCount++;
96+ }
97+ XML_ParserFree(parser);
98+ }
99+
100+ if (failCount) {
101+ fail("Namespace separator handling is broken");
102+ }
103+}
104+END_TEST
105+
106 /* Control variable; the number of times duff_allocator() will successfully
107 * allocate */
108 #define ALLOC_ALWAYS_SUCCEED (-1)
109@@ -11905,6 +11934,7 @@ make_suite(void) {
110 tcase_add_test(tc_namespace, test_ns_utf16_doctype);
111 tcase_add_test(tc_namespace, test_ns_invalid_doctype);
112 tcase_add_test(tc_namespace, test_ns_double_colon_doctype);
113+ tcase_add_test(tc_namespace, test_ns_separator_in_uri);
114
115 suite_add_tcase(s, tc_misc);
116 tcase_add_checked_fixture(tc_misc, NULL, basic_teardown);
diff --git a/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch
new file mode 100644
index 0000000000..0f14c9631b
--- /dev/null
+++ b/meta/recipes-core/expat/expat/CVE-2022-25236-2.patch
@@ -0,0 +1,232 @@
1Upstream-Status: Backport [https://github.com/libexpat/libexpat/commit/f178826b]
2CVE: CVE-2022-25236
3
4The commit is a merge commit, and this patch is created by:
5
6$ git show -m -p --stat f178826b
7
8Remove changes for expat/Changes and reference.html which fail to be applied.
9
10Signed-off-by: Kai Kang <kai.kang@windriver.com>
11
12commit f178826bb1e9c8ee23202f1be55ad4ac7b649e84 (from c99e0e7f2b15b48848038992ecbb4480f957cfe9)
13Merge: c99e0e7f 9579f7ea
14Author: Sebastian Pipping <sebastian@pipping.org>
15Date: Fri Mar 4 18:43:39 2022 +0100
16
17 Merge pull request #577 from libexpat/namesep
18
19 lib: Relax fix to CVE-2022-25236 with regard to RFC 3986 URI characters (fixes #572)
20---
21 expat/Changes | 16 ++++++
22 expat/doc/reference.html | 8 +++
23 expat/lib/expat.h | 11 ++++
24 expat/lib/xmlparse.c | 139 ++++++++++++++++++++++++++++++++++++++++++++---
25 expat/tests/runtests.c | 8 ++-
26 5 files changed, 171 insertions(+), 11 deletions(-)
27
28diff --git a/lib/expat.h b/lib/expat.h
29index 5ab493f7..181fc960 100644
30--- a/lib/expat.h
31+++ b/lib/expat.h
32@@ -239,6 +239,17 @@ XML_ParserCreate(const XML_Char *encoding);
33 and the local part will be concatenated without any separator.
34 It is a programming error to use the separator '\0' with namespace
35 triplets (see XML_SetReturnNSTriplet).
36+ If a namespace separator is chosen that can be part of a URI or
37+ part of an XML name, splitting an expanded name back into its
38+ 1, 2 or 3 original parts on application level in the element handler
39+ may end up vulnerable, so these are advised against; sane choices for
40+ a namespace separator are e.g. '\n' (line feed) and '|' (pipe).
41+
42+ Note that Expat does not validate namespace URIs (beyond encoding)
43+ against RFC 3986 today (and is not required to do so with regard to
44+ the XML 1.0 namespaces specification) but it may start doing that
45+ in future releases. Before that, an application using Expat must
46+ be ready to receive namespace URIs containing non-URI characters.
47 */
48 XMLPARSEAPI(XML_Parser)
49 XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
50diff --git a/lib/xmlparse.c b/lib/xmlparse.c
51index 59da19c8..6fe2cf1e 100644
52--- a/lib/xmlparse.c
53+++ b/lib/xmlparse.c
54@@ -3705,6 +3705,117 @@ storeAtts(XML_Parser parser, const ENCODING *enc, const char *attStr,
55 return XML_ERROR_NONE;
56 }
57
58+static XML_Bool
59+is_rfc3986_uri_char(XML_Char candidate) {
60+ // For the RFC 3986 ANBF grammar see
61+ // https://datatracker.ietf.org/doc/html/rfc3986#appendix-A
62+
63+ switch (candidate) {
64+ // From rule "ALPHA" (uppercase half)
65+ case 'A':
66+ case 'B':
67+ case 'C':
68+ case 'D':
69+ case 'E':
70+ case 'F':
71+ case 'G':
72+ case 'H':
73+ case 'I':
74+ case 'J':
75+ case 'K':
76+ case 'L':
77+ case 'M':
78+ case 'N':
79+ case 'O':
80+ case 'P':
81+ case 'Q':
82+ case 'R':
83+ case 'S':
84+ case 'T':
85+ case 'U':
86+ case 'V':
87+ case 'W':
88+ case 'X':
89+ case 'Y':
90+ case 'Z':
91+
92+ // From rule "ALPHA" (lowercase half)
93+ case 'a':
94+ case 'b':
95+ case 'c':
96+ case 'd':
97+ case 'e':
98+ case 'f':
99+ case 'g':
100+ case 'h':
101+ case 'i':
102+ case 'j':
103+ case 'k':
104+ case 'l':
105+ case 'm':
106+ case 'n':
107+ case 'o':
108+ case 'p':
109+ case 'q':
110+ case 'r':
111+ case 's':
112+ case 't':
113+ case 'u':
114+ case 'v':
115+ case 'w':
116+ case 'x':
117+ case 'y':
118+ case 'z':
119+
120+ // From rule "DIGIT"
121+ case '0':
122+ case '1':
123+ case '2':
124+ case '3':
125+ case '4':
126+ case '5':
127+ case '6':
128+ case '7':
129+ case '8':
130+ case '9':
131+
132+ // From rule "pct-encoded"
133+ case '%':
134+
135+ // From rule "unreserved"
136+ case '-':
137+ case '.':
138+ case '_':
139+ case '~':
140+
141+ // From rule "gen-delims"
142+ case ':':
143+ case '/':
144+ case '?':
145+ case '#':
146+ case '[':
147+ case ']':
148+ case '@':
149+
150+ // From rule "sub-delims"
151+ case '!':
152+ case '$':
153+ case '&':
154+ case '\'':
155+ case '(':
156+ case ')':
157+ case '*':
158+ case '+':
159+ case ',':
160+ case ';':
161+ case '=':
162+ return XML_TRUE;
163+
164+ default:
165+ return XML_FALSE;
166+ }
167+}
168+
169 /* addBinding() overwrites the value of prefix->binding without checking.
170 Therefore one must keep track of the old value outside of addBinding().
171 */
172@@ -3763,14 +3874,26 @@ addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId,
173 && (len > xmlnsLen || uri[len] != xmlnsNamespace[len]))
174 isXMLNS = XML_FALSE;
175
176- // NOTE: While Expat does not validate namespace URIs against RFC 3986,
177- // we have to at least make sure that the XML processor on top of
178- // Expat (that is splitting tag names by namespace separator into
179- // 2- or 3-tuples (uri-local or uri-local-prefix)) cannot be confused
180- // by an attacker putting additional namespace separator characters
181- // into namespace declarations. That would be ambiguous and not to
182- // be expected.
183- if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)) {
184+ // NOTE: While Expat does not validate namespace URIs against RFC 3986
185+ // today (and is not REQUIRED to do so with regard to the XML 1.0
186+ // namespaces specification) we have to at least make sure, that
187+ // the application on top of Expat (that is likely splitting expanded
188+ // element names ("qualified names") of form
189+ // "[uri sep] local [sep prefix] '\0'" back into 1, 2 or 3 pieces
190+ // in its element handler code) cannot be confused by an attacker
191+ // putting additional namespace separator characters into namespace
192+ // declarations. That would be ambiguous and not to be expected.
193+ //
194+ // While the HTML API docs of function XML_ParserCreateNS have been
195+ // advising against use of a namespace separator character that can
196+ // appear in a URI for >20 years now, some widespread applications
197+ // are using URI characters (':' (colon) in particular) for a
198+ // namespace separator, in practice. To keep these applications
199+ // functional, we only reject namespaces URIs containing the
200+ // application-chosen namespace separator if the chosen separator
201+ // is a non-URI character with regard to RFC 3986.
202+ if (parser->m_ns && (uri[len] == parser->m_namespaceSeparator)
203+ && ! is_rfc3986_uri_char(uri[len])) {
204 return XML_ERROR_SYNTAX;
205 }
206 }
207diff --git a/tests/runtests.c b/tests/runtests.c
208index 60da868e..712706c4 100644
209--- a/tests/runtests.c
210+++ b/tests/runtests.c
211@@ -7406,16 +7406,18 @@ START_TEST(test_ns_separator_in_uri) {
212 struct test_case {
213 enum XML_Status expectedStatus;
214 const char *doc;
215+ XML_Char namesep;
216 };
217 struct test_case cases[] = {
218- {XML_STATUS_OK, "<doc xmlns='one_two' />"},
219- {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />"},
220+ {XML_STATUS_OK, "<doc xmlns='one_two' />", XCS('\n')},
221+ {XML_STATUS_ERROR, "<doc xmlns='one&#x0A;two' />", XCS('\n')},
222+ {XML_STATUS_OK, "<doc xmlns='one:two' />", XCS(':')},
223 };
224
225 size_t i = 0;
226 size_t failCount = 0;
227 for (; i < sizeof(cases) / sizeof(cases[0]); i++) {
228- XML_Parser parser = XML_ParserCreateNS(NULL, '\n');
229+ XML_Parser parser = XML_ParserCreateNS(NULL, cases[i].namesep);
230 XML_SetElementHandler(parser, dummy_start_element, dummy_end_element);
231 if (XML_Parse(parser, cases[i].doc, (int)strlen(cases[i].doc),
232 /*isFinal*/ XML_TRUE)
diff --git a/meta/recipes-core/expat/expat_2.2.10.bb b/meta/recipes-core/expat/expat_2.2.10.bb
index 08e8ff1cea..f99fa7edb6 100644
--- a/meta/recipes-core/expat/expat_2.2.10.bb
+++ b/meta/recipes-core/expat/expat_2.2.10.bb
@@ -10,9 +10,17 @@ VERSION_TAG = "${@d.getVar('PV').replace('.', '_')}"
10 10
11SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \ 11SRC_URI = "https://github.com/libexpat/libexpat/releases/download/R_${VERSION_TAG}/expat-${PV}.tar.bz2 \
12 file://libtool-tag.patch \ 12 file://libtool-tag.patch \
13 file://run-ptest \ 13 file://run-ptest \
14 file://0001-Add-output-of-tests-result.patch \ 14 file://0001-Add-output-of-tests-result.patch \
15 " 15 file://CVE-2022-22822-27.patch \
16 file://CVE-2021-45960.patch \
17 file://CVE-2021-46143.patch \
18 file://CVE-2022-23852.patch \
19 file://CVE-2022-23990.patch \
20 file://CVE-2022-25235.patch \
21 file://CVE-2022-25236-1.patch \
22 file://CVE-2022-25236-2.patch \
23 "
16 24
17UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/" 25UPSTREAM_CHECK_URI = "https://github.com/libexpat/libexpat/releases/"
18 26
diff --git a/meta/recipes-core/glibc/glibc-version.inc b/meta/recipes-core/glibc/glibc-version.inc
index 4d69187961..e1eefdee49 100644
--- a/meta/recipes-core/glibc/glibc-version.inc
+++ b/meta/recipes-core/glibc/glibc-version.inc
@@ -1,6 +1,6 @@
1SRCBRANCH ?= "release/2.33/master" 1SRCBRANCH ?= "release/2.33/master"
2PV = "2.33" 2PV = "2.33"
3SRCREV_glibc ?= "6090cf1330faf2deb17285758f327cb23b89ebf1" 3SRCREV_glibc ?= "3e2a15c666e40e5ee740e5079c56d83469280323"
4SRCREV_localedef ?= "bd644c9e6f3e20c5504da1488448173c69c56c28" 4SRCREV_localedef ?= "bd644c9e6f3e20c5504da1488448173c69c56c28"
5 5
6GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git" 6GLIBC_GIT_URI ?= "git://sourceware.org/git/glibc.git"
diff --git a/meta/recipes-core/glibc/glibc_2.33.bb b/meta/recipes-core/glibc/glibc_2.33.bb
index ad5e2b8eb1..a1e9eb3a16 100644
--- a/meta/recipes-core/glibc/glibc_2.33.bb
+++ b/meta/recipes-core/glibc/glibc_2.33.bb
@@ -88,7 +88,7 @@ EXTRA_OECONF = "--enable-kernel=${OLDEST_KERNEL} \
88 88
89EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}" 89EXTRA_OECONF += "${@get_libc_fpu_setting(bb, d)}"
90 90
91EXTRA_OECONF_append_x86 = " --enable-cet" 91EXTRA_OECONF_append_x86 = " ${@bb.utils.contains_any('TUNE_FEATURES', 'i586 c3', '--disable-cet', '--enable-cet', d)}"
92EXTRA_OECONF_append_x86-64 = " --enable-cet" 92EXTRA_OECONF_append_x86-64 = " --enable-cet"
93 93
94PACKAGECONFIG ??= "nscd" 94PACKAGECONFIG ??= "nscd"
diff --git a/meta/recipes-core/images/build-appliance-image_15.0.0.bb b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
index 455fe825c8..5631cd8ae6 100644
--- a/meta/recipes-core/images/build-appliance-image_15.0.0.bb
+++ b/meta/recipes-core/images/build-appliance-image_15.0.0.bb
@@ -24,7 +24,7 @@ IMAGE_FSTYPES = "wic.vmdk wic.vhd wic.vhdx"
24 24
25inherit core-image setuptools3 25inherit core-image setuptools3
26 26
27SRCREV ?= "ec3ac9d883d53ebbf3c6b9a80694df69c9e9ccc7" 27SRCREV ?= "2954fa87a4d325f1a3c722d6fb8bf13b17f9e7a0"
28SRC_URI = "git://git.yoctoproject.org/poky;branch=hardknott \ 28SRC_URI = "git://git.yoctoproject.org/poky;branch=hardknott \
29 file://Yocto_Build_Appliance.vmx \ 29 file://Yocto_Build_Appliance.vmx \
30 file://Yocto_Build_Appliance.vmxf \ 30 file://Yocto_Build_Appliance.vmxf \
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/finish b/meta/recipes-core/initrdscripts/initramfs-framework/finish
index 717383ebac..f08a920867 100755
--- a/meta/recipes-core/initrdscripts/initramfs-framework/finish
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/finish
@@ -12,6 +12,18 @@ finish_run() {
12 fatal "ERROR: There's no '/dev' on rootfs." 12 fatal "ERROR: There's no '/dev' on rootfs."
13 fi 13 fi
14 14
15 # Unmount anything that was automounted by busybox via mdev-mount.sh.
16 # We're about to switch_root, and leaving anything mounted will prevent
17 # the next rootfs from modifying the block device. Ignore ROOT_DISK,
18 # if it was set by setup-live, because it'll be mounted over loopback
19 # to ROOTFS_DIR.
20 local dev
21 for dev in /run/media/*; do
22 if mountpoint -q "${dev}" && [ "${dev##*/}" != "${ROOT_DISK}" ]; then
23 umount -f "${dev}" || debug "Failed to unmount ${dev}"
24 fi
25 done
26
15 info "Switching root to '$ROOTFS_DIR'..." 27 info "Switching root to '$ROOTFS_DIR'..."
16 28
17 debug "Moving /dev, /proc and /sys onto rootfs..." 29 debug "Moving /dev, /proc and /sys onto rootfs..."
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch
new file mode 100644
index 0000000000..eefecb9adb
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308-fix-regression.patch
@@ -0,0 +1,99 @@
1From 646fe48d1c8a74310c409ddf81fe7df6700052af Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Tue, 22 Feb 2022 11:51:08 +0100
4Subject: [PATCH] Fix --without-valid build
5
6Regressed in commit 652dd12a.
7---
8 valid.c | 58 ++++++++++++++++++++++++++++-----------------------------
9 1 file changed, 29 insertions(+), 29 deletions(-)
10---
11
12From https://github.com/GNOME/libxml2.git
13 commit 646fe48d1c8a74310c409ddf81fe7df6700052af
14
15CVE: CVE-2022-23308
16Upstream-status: Backport
17
18Signed-off-by: Joe Slater <joe.slater@windriver.com>
19
20
21diff --git a/valid.c b/valid.c
22index 8e596f1d..9684683a 100644
23--- a/valid.c
24+++ b/valid.c
25@@ -479,35 +479,6 @@ nodeVPop(xmlValidCtxtPtr ctxt)
26 return (ret);
27 }
28
29-/**
30- * xmlValidNormalizeString:
31- * @str: a string
32- *
33- * Normalize a string in-place.
34- */
35-static void
36-xmlValidNormalizeString(xmlChar *str) {
37- xmlChar *dst;
38- const xmlChar *src;
39-
40- if (str == NULL)
41- return;
42- src = str;
43- dst = str;
44-
45- while (*src == 0x20) src++;
46- while (*src != 0) {
47- if (*src == 0x20) {
48- while (*src == 0x20) src++;
49- if (*src != 0)
50- *dst++ = 0x20;
51- } else {
52- *dst++ = *src++;
53- }
54- }
55- *dst = 0;
56-}
57-
58 #ifdef DEBUG_VALID_ALGO
59 static void
60 xmlValidPrintNode(xmlNodePtr cur) {
61@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
62 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
63 xmlFree((char *)(str));
64
65+/**
66+ * xmlValidNormalizeString:
67+ * @str: a string
68+ *
69+ * Normalize a string in-place.
70+ */
71+static void
72+xmlValidNormalizeString(xmlChar *str) {
73+ xmlChar *dst;
74+ const xmlChar *src;
75+
76+ if (str == NULL)
77+ return;
78+ src = str;
79+ dst = str;
80+
81+ while (*src == 0x20) src++;
82+ while (*src != 0) {
83+ if (*src == 0x20) {
84+ while (*src == 0x20) src++;
85+ if (*src != 0)
86+ *dst++ = 0x20;
87+ } else {
88+ *dst++ = *src++;
89+ }
90+ }
91+ *dst = 0;
92+}
93+
94 static int
95 xmlIsStreaming(xmlValidCtxtPtr ctxt) {
96 xmlParserCtxtPtr pctxt;
97--
982.35.1
99
diff --git a/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch
new file mode 100644
index 0000000000..708a98b45a
--- /dev/null
+++ b/meta/recipes-core/libxml/libxml2/CVE-2022-23308.patch
@@ -0,0 +1,209 @@
1From 652dd12a858989b14eed4e84e453059cd3ba340e Mon Sep 17 00:00:00 2001
2From: Nick Wellnhofer <wellnhofer@aevum.de>
3Date: Tue, 8 Feb 2022 03:29:24 +0100
4Subject: [PATCH] [CVE-2022-23308] Use-after-free of ID and IDREF attributes
5
6If a document is parsed with XML_PARSE_DTDVALID and without
7XML_PARSE_NOENT, the value of ID attributes has to be normalized after
8potentially expanding entities in xmlRemoveID. Otherwise, later calls
9to xmlGetID can return a pointer to previously freed memory.
10
11ID attributes which are empty or contain only whitespace after
12entity expansion are affected in a similar way. This is fixed by
13not storing such attributes in the ID table.
14
15The test to detect streaming mode when validating against a DTD was
16broken. In connection with the defects above, this could result in a
17use-after-free when using the xmlReader interface with validation.
18Fix detection of streaming mode to avoid similar issues. (This changes
19the expected result of a test case. But as far as I can tell, using the
20XML reader with XIncludes referencing the root document never worked
21properly, anyway.)
22
23All of these issues can result in denial of service. Using xmlReader
24with validation could result in disclosure of memory via the error
25channel, typically stderr. The security impact of xmlGetID returning
26a pointer to freed memory depends on the application. The typical use
27case of calling xmlGetID on an unmodified document is not affected.
28---
29 result/XInclude/ns1.xml.rdr | 2 +-
30 valid.c | 88 +++++++++++++++++++++++--------------
31 2 files changed, 56 insertions(+), 34 deletions(-)
32 ---
33
34From https://github.com/GNOME/libxml2.git
35 commit 652dd12a858989b14eed4e84e453059cd3ba340e
36
37Remove patch to ns1.xml.rdr which does not exist in version 2.9.10.
38
39CVE: CVE-2022-23308
40Upstream-status: Backport
41
42Signed-off-by: Joe Slater <joe.slater@windriver.com>
43
44
45diff --git a/valid.c b/valid.c
46index 5ee391c0..8e596f1d 100644
47--- a/valid.c
48+++ b/valid.c
49@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt)
50 return (ret);
51 }
52
53+/**
54+ * xmlValidNormalizeString:
55+ * @str: a string
56+ *
57+ * Normalize a string in-place.
58+ */
59+static void
60+xmlValidNormalizeString(xmlChar *str) {
61+ xmlChar *dst;
62+ const xmlChar *src;
63+
64+ if (str == NULL)
65+ return;
66+ src = str;
67+ dst = str;
68+
69+ while (*src == 0x20) src++;
70+ while (*src != 0) {
71+ if (*src == 0x20) {
72+ while (*src == 0x20) src++;
73+ if (*src != 0)
74+ *dst++ = 0x20;
75+ } else {
76+ *dst++ = *src++;
77+ }
78+ }
79+ *dst = 0;
80+}
81+
82 #ifdef DEBUG_VALID_ALGO
83 static void
84 xmlValidPrintNode(xmlNodePtr cur) {
85@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
86 (xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
87 xmlFree((char *)(str));
88
89+static int
90+xmlIsStreaming(xmlValidCtxtPtr ctxt) {
91+ xmlParserCtxtPtr pctxt;
92+
93+ if (ctxt == NULL)
94+ return(0);
95+ /*
96+ * These magic values are also abused to detect whether we're validating
97+ * while parsing a document. In this case, userData points to the parser
98+ * context.
99+ */
100+ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) &&
101+ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1))
102+ return(0);
103+ pctxt = ctxt->userData;
104+ return(pctxt->parseMode == XML_PARSE_READER);
105+}
106+
107 /**
108 * xmlFreeID:
109 * @not: A id
110@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
111 if (doc == NULL) {
112 return(NULL);
113 }
114- if (value == NULL) {
115+ if ((value == NULL) || (value[0] == 0)) {
116 return(NULL);
117 }
118 if (attr == NULL) {
119@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
120 */
121 ret->value = xmlStrdup(value);
122 ret->doc = doc;
123- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
124+ if (xmlIsStreaming(ctxt)) {
125 /*
126 * Operating in streaming mode, attr is gonna disappear
127 */
128@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
129 ID = xmlNodeListGetString(doc, attr->children, 1);
130 if (ID == NULL)
131 return(-1);
132+ xmlValidNormalizeString(ID);
133
134 id = xmlHashLookup(table, ID);
135 if (id == NULL || id->attr != attr) {
136@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
137 * fill the structure.
138 */
139 ret->value = xmlStrdup(value);
140- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
141+ if (xmlIsStreaming(ctxt)) {
142 /*
143 * Operating in streaming mode, attr is gonna disappear
144 */
145@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
146 xmlChar *
147 xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
148 xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
149- xmlChar *ret, *dst;
150- const xmlChar *src;
151+ xmlChar *ret;
152 xmlAttributePtr attrDecl = NULL;
153 int extsubset = 0;
154
155@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
156 ret = xmlStrdup(value);
157 if (ret == NULL)
158 return(NULL);
159- src = value;
160- dst = ret;
161- while (*src == 0x20) src++;
162- while (*src != 0) {
163- if (*src == 0x20) {
164- while (*src == 0x20) src++;
165- if (*src != 0)
166- *dst++ = 0x20;
167- } else {
168- *dst++ = *src++;
169- }
170- }
171- *dst = 0;
172+ xmlValidNormalizeString(ret);
173 if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
174 xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
175 "standalone: %s on %s value had to be normalized based on external subset declaration\n",
176@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
177 xmlChar *
178 xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
179 const xmlChar *name, const xmlChar *value) {
180- xmlChar *ret, *dst;
181- const xmlChar *src;
182+ xmlChar *ret;
183 xmlAttributePtr attrDecl = NULL;
184
185 if (doc == NULL) return(NULL);
186@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
187 ret = xmlStrdup(value);
188 if (ret == NULL)
189 return(NULL);
190- src = value;
191- dst = ret;
192- while (*src == 0x20) src++;
193- while (*src != 0) {
194- if (*src == 0x20) {
195- while (*src == 0x20) src++;
196- if (*src != 0)
197- *dst++ = 0x20;
198- } else {
199- *dst++ = *src++;
200- }
201- }
202- *dst = 0;
203+ xmlValidNormalizeString(ret);
204 return(ret);
205 }
206
207--
2082.25.1
209
diff --git a/meta/recipes-core/libxml/libxml2_2.9.10.bb b/meta/recipes-core/libxml/libxml2_2.9.10.bb
index cabf911816..778312f662 100644
--- a/meta/recipes-core/libxml/libxml2_2.9.10.bb
+++ b/meta/recipes-core/libxml/libxml2_2.9.10.bb
@@ -30,6 +30,8 @@ SRC_URI = "http://www.xmlsoft.org/sources/libxml2-${PV}.tar.gz;name=libtar \
30 file://CVE-2021-3518-0002.patch \ 30 file://CVE-2021-3518-0002.patch \
31 file://CVE-2021-3537.patch \ 31 file://CVE-2021-3537.patch \
32 file://CVE-2021-3541.patch \ 32 file://CVE-2021-3541.patch \
33 file://CVE-2022-23308.patch \
34 file://CVE-2022-23308-fix-regression.patch \
33 " 35 "
34 36
35SRC_URI[libtar.md5sum] = "10942a1dc23137a8aa07f0639cbfece5" 37SRC_URI[libtar.md5sum] = "10942a1dc23137a8aa07f0639cbfece5"
diff --git a/meta/recipes-core/os-release/os-release.bb b/meta/recipes-core/os-release/os-release.bb
index a29d678125..33f75e39b8 100644
--- a/meta/recipes-core/os-release/os-release.bb
+++ b/meta/recipes-core/os-release/os-release.bb
@@ -12,7 +12,9 @@ do_configure[noexec] = "1"
12 12
13# Other valid fields: BUILD_ID ID_LIKE ANSI_COLOR CPE_NAME 13# Other valid fields: BUILD_ID ID_LIKE ANSI_COLOR CPE_NAME
14# HOME_URL SUPPORT_URL BUG_REPORT_URL 14# HOME_URL SUPPORT_URL BUG_REPORT_URL
15OS_RELEASE_FIELDS = "ID ID_LIKE NAME VERSION VERSION_ID PRETTY_NAME" 15OS_RELEASE_FIELDS = "\
16 ID ID_LIKE NAME VERSION VERSION_ID PRETTY_NAME DISTRO_CODENAME \
17"
16OS_RELEASE_UNQUOTED_FIELDS = "ID VERSION_ID VARIANT_ID" 18OS_RELEASE_UNQUOTED_FIELDS = "ID VERSION_ID VARIANT_ID"
17 19
18ID = "${DISTRO}" 20ID = "${DISTRO}"
diff --git a/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch
new file mode 100644
index 0000000000..5cb6183641
--- /dev/null
+++ b/meta/recipes-core/zlib/zlib/CVE-2018-25032.patch
@@ -0,0 +1,347 @@
1CVE: CVE-2018-25032
2Upstream-Status: Backport
3Signed-off-by: Ross Burton <ross.burton@arm.com>
4
5From 5c44459c3b28a9bd3283aaceab7c615f8020c531 Mon Sep 17 00:00:00 2001
6From: Mark Adler <madler@alumni.caltech.edu>
7Date: Tue, 17 Apr 2018 22:09:22 -0700
8Subject: [PATCH] Fix a bug that can crash deflate on some input when using
9 Z_FIXED.
10
11This bug was reported by Danilo Ramos of Eideticom, Inc. It has
12lain in wait 13 years before being found! The bug was introduced
13in zlib 1.2.2.2, with the addition of the Z_FIXED option. That
14option forces the use of fixed Huffman codes. For rare inputs with
15a large number of distant matches, the pending buffer into which
16the compressed data is written can overwrite the distance symbol
17table which it overlays. That results in corrupted output due to
18invalid distances, and can result in out-of-bound accesses,
19crashing the application.
20
21The fix here combines the distance buffer and literal/length
22buffers into a single symbol buffer. Now three bytes of pending
23buffer space are opened up for each literal or length/distance
24pair consumed, instead of the previous two bytes. This assures
25that the pending buffer cannot overwrite the symbol table, since
26the maximum fixed code compressed length/distance is 31 bits, and
27since there are four bytes of pending space for every three bytes
28of symbol space.
29---
30 deflate.c | 74 ++++++++++++++++++++++++++++++++++++++++---------------
31 deflate.h | 25 +++++++++----------
32 trees.c | 50 +++++++++++--------------------------
33 3 files changed, 79 insertions(+), 70 deletions(-)
34
35diff --git a/deflate.c b/deflate.c
36index 425babc00..19cba873a 100644
37--- a/deflate.c
38+++ b/deflate.c
39@@ -255,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
40 int wrap = 1;
41 static const char my_version[] = ZLIB_VERSION;
42
43- ushf *overlay;
44- /* We overlay pending_buf and d_buf+l_buf. This works since the average
45- * output size for (length,distance) codes is <= 24 bits.
46- */
47-
48 if (version == Z_NULL || version[0] != my_version[0] ||
49 stream_size != sizeof(z_stream)) {
50 return Z_VERSION_ERROR;
51@@ -329,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
52
53 s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
54
55- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
56- s->pending_buf = (uchf *) overlay;
57- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
58+ /* We overlay pending_buf and sym_buf. This works since the average size
59+ * for length/distance pairs over any compressed block is assured to be 31
60+ * bits or less.
61+ *
62+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
63+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
64+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
65+ * possible fixed-codes length/distance pair is then 31 bits total.
66+ *
67+ * sym_buf starts one-fourth of the way into pending_buf. So there are
68+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
69+ * in sym_buf is three bytes -- two for the distance and one for the
70+ * literal/length. As each symbol is consumed, the pointer to the next
71+ * sym_buf value to read moves forward three bytes. From that symbol, up to
72+ * 31 bits are written to pending_buf. The closest the written pending_buf
73+ * bits gets to the next sym_buf symbol to read is just before the last
74+ * code is written. At that time, 31*(n-2) bits have been written, just
75+ * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
76+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
77+ * symbols are written.) The closest the writing gets to what is unread is
78+ * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
79+ * can range from 128 to 32768.
80+ *
81+ * Therefore, at a minimum, there are 142 bits of space between what is
82+ * written and what is read in the overlain buffers, so the symbols cannot
83+ * be overwritten by the compressed data. That space is actually 139 bits,
84+ * due to the three-bit fixed-code block header.
85+ *
86+ * That covers the case where either Z_FIXED is specified, forcing fixed
87+ * codes, or when the use of fixed codes is chosen, because that choice
88+ * results in a smaller compressed block than dynamic codes. That latter
89+ * condition then assures that the above analysis also covers all dynamic
90+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
91+ * fewer bits than a fixed-code block would for the same set of symbols.
92+ * Therefore its average symbol length is assured to be less than 31. So
93+ * the compressed data for a dynamic block also cannot overwrite the
94+ * symbols from which it is being constructed.
95+ */
96+
97+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
98+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
99
100 if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
101 s->pending_buf == Z_NULL) {
102@@ -340,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
103 deflateEnd (strm);
104 return Z_MEM_ERROR;
105 }
106- s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
107- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
108+ s->sym_buf = s->pending_buf + s->lit_bufsize;
109+ s->sym_end = (s->lit_bufsize - 1) * 3;
110+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
111+ * on 16 bit machines and because stored blocks are restricted to
112+ * 64K-1 bytes.
113+ */
114
115 s->level = level;
116 s->strategy = strategy;
117@@ -552,7 +589,7 @@ int ZEXPORT deflatePrime (strm, bits, value)
118
119 if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
120 s = strm->state;
121- if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
122+ if (s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
123 return Z_BUF_ERROR;
124 do {
125 put = Buf_size - s->bi_valid;
126@@ -1113,7 +1150,6 @@ int ZEXPORT deflateCopy (dest, source)
127 #else
128 deflate_state *ds;
129 deflate_state *ss;
130- ushf *overlay;
131
132
133 if (deflateStateCheck(source) || dest == Z_NULL) {
134@@ -1133,8 +1169,7 @@ int ZEXPORT deflateCopy (dest, source)
135 ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
136 ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
137 ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
138- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
139- ds->pending_buf = (uchf *) overlay;
140+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
141
142 if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
143 ds->pending_buf == Z_NULL) {
144@@ -1148,8 +1183,7 @@ int ZEXPORT deflateCopy (dest, source)
145 zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
146
147 ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
148- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
149- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
150+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
151
152 ds->l_desc.dyn_tree = ds->dyn_ltree;
153 ds->d_desc.dyn_tree = ds->dyn_dtree;
154@@ -1925,7 +1959,7 @@ local block_state deflate_fast(s, flush)
155 FLUSH_BLOCK(s, 1);
156 return finish_done;
157 }
158- if (s->last_lit)
159+ if (s->sym_next)
160 FLUSH_BLOCK(s, 0);
161 return block_done;
162 }
163@@ -2056,7 +2090,7 @@ local block_state deflate_slow(s, flush)
164 FLUSH_BLOCK(s, 1);
165 return finish_done;
166 }
167- if (s->last_lit)
168+ if (s->sym_next)
169 FLUSH_BLOCK(s, 0);
170 return block_done;
171 }
172@@ -2131,7 +2165,7 @@ local block_state deflate_rle(s, flush)
173 FLUSH_BLOCK(s, 1);
174 return finish_done;
175 }
176- if (s->last_lit)
177+ if (s->sym_next)
178 FLUSH_BLOCK(s, 0);
179 return block_done;
180 }
181@@ -2170,7 +2204,7 @@ local block_state deflate_huff(s, flush)
182 FLUSH_BLOCK(s, 1);
183 return finish_done;
184 }
185- if (s->last_lit)
186+ if (s->sym_next)
187 FLUSH_BLOCK(s, 0);
188 return block_done;
189 }
190diff --git a/deflate.h b/deflate.h
191index 23ecdd312..d4cf1a98b 100644
192--- a/deflate.h
193+++ b/deflate.h
194@@ -217,7 +217,7 @@ typedef struct internal_state {
195 /* Depth of each subtree used as tie breaker for trees of equal frequency
196 */
197
198- uchf *l_buf; /* buffer for literals or lengths */
199+ uchf *sym_buf; /* buffer for distances and literals/lengths */
200
201 uInt lit_bufsize;
202 /* Size of match buffer for literals/lengths. There are 4 reasons for
203@@ -239,13 +239,8 @@ typedef struct internal_state {
204 * - I can't count above 4
205 */
206
207- uInt last_lit; /* running index in l_buf */
208-
209- ushf *d_buf;
210- /* Buffer for distances. To simplify the code, d_buf and l_buf have
211- * the same number of elements. To use different lengths, an extra flag
212- * array would be necessary.
213- */
214+ uInt sym_next; /* running index in sym_buf */
215+ uInt sym_end; /* symbol table full when sym_next reaches this */
216
217 ulg opt_len; /* bit length of current block with optimal trees */
218 ulg static_len; /* bit length of current block with static trees */
219@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
220
221 # define _tr_tally_lit(s, c, flush) \
222 { uch cc = (c); \
223- s->d_buf[s->last_lit] = 0; \
224- s->l_buf[s->last_lit++] = cc; \
225+ s->sym_buf[s->sym_next++] = 0; \
226+ s->sym_buf[s->sym_next++] = 0; \
227+ s->sym_buf[s->sym_next++] = cc; \
228 s->dyn_ltree[cc].Freq++; \
229- flush = (s->last_lit == s->lit_bufsize-1); \
230+ flush = (s->sym_next == s->sym_end); \
231 }
232 # define _tr_tally_dist(s, distance, length, flush) \
233 { uch len = (uch)(length); \
234 ush dist = (ush)(distance); \
235- s->d_buf[s->last_lit] = dist; \
236- s->l_buf[s->last_lit++] = len; \
237+ s->sym_buf[s->sym_next++] = dist; \
238+ s->sym_buf[s->sym_next++] = dist >> 8; \
239+ s->sym_buf[s->sym_next++] = len; \
240 dist--; \
241 s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
242 s->dyn_dtree[d_code(dist)].Freq++; \
243- flush = (s->last_lit == s->lit_bufsize-1); \
244+ flush = (s->sym_next == s->sym_end); \
245 }
246 #else
247 # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
248diff --git a/trees.c b/trees.c
249index 4f4a65011..decaeb7c3 100644
250--- a/trees.c
251+++ b/trees.c
252@@ -416,7 +416,7 @@ local void init_block(s)
253
254 s->dyn_ltree[END_BLOCK].Freq = 1;
255 s->opt_len = s->static_len = 0L;
256- s->last_lit = s->matches = 0;
257+ s->sym_next = s->matches = 0;
258 }
259
260 #define SMALLEST 1
261@@ -948,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
262
263 Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
264 opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
265- s->last_lit));
266+ s->sym_next / 3));
267
268 if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
269
270@@ -1017,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
271 unsigned dist; /* distance of matched string */
272 unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
273 {
274- s->d_buf[s->last_lit] = (ush)dist;
275- s->l_buf[s->last_lit++] = (uch)lc;
276+ s->sym_buf[s->sym_next++] = dist;
277+ s->sym_buf[s->sym_next++] = dist >> 8;
278+ s->sym_buf[s->sym_next++] = lc;
279 if (dist == 0) {
280 /* lc is the unmatched char */
281 s->dyn_ltree[lc].Freq++;
282@@ -1033,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
283 s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
284 s->dyn_dtree[d_code(dist)].Freq++;
285 }
286-
287-#ifdef TRUNCATE_BLOCK
288- /* Try to guess if it is profitable to stop the current block here */
289- if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
290- /* Compute an upper bound for the compressed length */
291- ulg out_length = (ulg)s->last_lit*8L;
292- ulg in_length = (ulg)((long)s->strstart - s->block_start);
293- int dcode;
294- for (dcode = 0; dcode < D_CODES; dcode++) {
295- out_length += (ulg)s->dyn_dtree[dcode].Freq *
296- (5L+extra_dbits[dcode]);
297- }
298- out_length >>= 3;
299- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
300- s->last_lit, in_length, out_length,
301- 100L - out_length*100L/in_length));
302- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
303- }
304-#endif
305- return (s->last_lit == s->lit_bufsize-1);
306- /* We avoid equality with lit_bufsize because of wraparound at 64K
307- * on 16 bit machines and because stored blocks are restricted to
308- * 64K-1 bytes.
309- */
310+ return (s->sym_next == s->sym_end);
311 }
312
313 /* ===========================================================================
314@@ -1069,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
315 {
316 unsigned dist; /* distance of matched string */
317 int lc; /* match length or unmatched char (if dist == 0) */
318- unsigned lx = 0; /* running index in l_buf */
319+ unsigned sx = 0; /* running index in sym_buf */
320 unsigned code; /* the code to send */
321 int extra; /* number of extra bits to send */
322
323- if (s->last_lit != 0) do {
324- dist = s->d_buf[lx];
325- lc = s->l_buf[lx++];
326+ if (s->sym_next != 0) do {
327+ dist = s->sym_buf[sx++] & 0xff;
328+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
329+ lc = s->sym_buf[sx++];
330 if (dist == 0) {
331 send_code(s, lc, ltree); /* send a literal byte */
332 Tracecv(isgraph(lc), (stderr," '%c' ", lc));
333@@ -1100,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
334 }
335 } /* literal or match pair ? */
336
337- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
338- Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
339- "pendingBuf overflow");
340+ /* Check that the overlay between pending_buf and sym_buf is ok: */
341+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
342
343- } while (lx < s->last_lit);
344+ } while (sx < s->sym_next);
345
346 send_code(s, END_BLOCK, ltree);
347 }
diff --git a/meta/recipes-core/zlib/zlib_1.2.11.bb b/meta/recipes-core/zlib/zlib_1.2.11.bb
index ef9431ae47..bc42cd64e9 100644
--- a/meta/recipes-core/zlib/zlib_1.2.11.bb
+++ b/meta/recipes-core/zlib/zlib_1.2.11.bb
@@ -8,6 +8,7 @@ LIC_FILES_CHKSUM = "file://zlib.h;beginline=6;endline=23;md5=5377232268e952e9ef6
8 8
9SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \ 9SRC_URI = "${SOURCEFORGE_MIRROR}/libpng/${BPN}/${PV}/${BPN}-${PV}.tar.xz \
10 file://ldflags-tests.patch \ 10 file://ldflags-tests.patch \
11 file://CVE-2018-25032.patch \
11 file://run-ptest \ 12 file://run-ptest \
12 " 13 "
13UPSTREAM_CHECK_URI = "http://zlib.net/" 14UPSTREAM_CHECK_URI = "http://zlib.net/"
diff --git a/meta/recipes-devtools/binutils/binutils-2.36.inc b/meta/recipes-devtools/binutils/binutils-2.36.inc
index 7d0824e060..fa28358c2d 100644
--- a/meta/recipes-devtools/binutils/binutils-2.36.inc
+++ b/meta/recipes-devtools/binutils/binutils-2.36.inc
@@ -24,7 +24,7 @@ BRANCH ?= "binutils-2_36-branch"
24 24
25UPSTREAM_CHECK_GITTAGREGEX = "binutils-(?P<pver>\d+_(\d_?)*)" 25UPSTREAM_CHECK_GITTAGREGEX = "binutils-(?P<pver>\d+_(\d_?)*)"
26 26
27SRCREV ?= "7651a4871c225925ffdfda0a8c91a6ed370cd9a1" 27SRCREV ?= "a281816c8aeb12619d34eec8959a43dfa5c6b4ec"
28BINUTILS_GIT_URI ?= "git://sourceware.org/git/binutils-gdb.git;branch=${BRANCH};protocol=git" 28BINUTILS_GIT_URI ?= "git://sourceware.org/git/binutils-gdb.git;branch=${BRANCH};protocol=git"
29SRC_URI = "\ 29SRC_URI = "\
30 ${BINUTILS_GIT_URI} \ 30 ${BINUTILS_GIT_URI} \
@@ -41,10 +41,9 @@ SRC_URI = "\
41 file://0014-Fix-rpath-in-libtool-when-sysroot-is-enabled.patch \ 41 file://0014-Fix-rpath-in-libtool-when-sysroot-is-enabled.patch \
42 file://0015-sync-with-OE-libtool-changes.patch \ 42 file://0015-sync-with-OE-libtool-changes.patch \
43 file://0016-Check-for-clang-before-checking-gcc-version.patch \ 43 file://0016-Check-for-clang-before-checking-gcc-version.patch \
44 file://0001-CVE-2021-20197.patch \
45 file://0002-CVE-2021-20197.patch \
46 file://0003-CVE-2021-20197.patch \
47 file://0017-CVE-2021-3530.patch \ 44 file://0017-CVE-2021-3530.patch \
48 file://0018-CVE-2021-3530.patch \ 45 file://0018-CVE-2021-3530.patch \
46 file://0001-CVE-2021-42574.patch \
47 file://0001-CVE-2021-45078.patch \
49" 48"
50S = "${WORKDIR}/git" 49S = "${WORKDIR}/git"
diff --git a/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-20197.patch b/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-20197.patch
deleted file mode 100644
index 2b4eaba26d..0000000000
--- a/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-20197.patch
+++ /dev/null
@@ -1,201 +0,0 @@
1From 8e03235147a9e774d3ba084e93c2da1aa94d1cec Mon Sep 17 00:00:00 2001
2From: Siddhesh Poyarekar <siddhesh@gotplt.org>
3Date: Mon, 22 Feb 2021 20:45:50 +0530
4Subject: [PATCH] binutils: Avoid renaming over existing files
5
6Renaming over existing files needs additional care to restore
7permissions and ownership, which may not always succeed.
8Additionally, other properties of the file such as extended attributes
9may be lost, making the operation flaky.
10
11For predictable results, resort to rename() only if the file does not
12exist, otherwise copy the file contents into the existing file. This
13ensures that no additional tricks are needed to retain file
14properties.
15
16This also allows dropping of the redundant set_times on the tmpfile in
17objcopy/strip since now we no longer rename over existing files.
18
19binutils/
20
21 * ar.c (write_archive): Adjust call to SMART_RENAME.
22 * arsup.c (ar_save): Likewise.
23 * objcopy (strip_main): Don't set times on temporary file and
24 adjust call to SMART_RENAME.
25 (copy_main): Likewise.
26 * rename.c [!S_ISLNK]: Remove definitions.
27 (try_preserve_permissions): Remove function.
28 (smart_rename): Replace PRESERVE_DATES argument with
29 TARGET_STAT. Use rename system call only if TO does not exist.
30 * bucomm.h (smart_rename): Adjust declaration.
31
32(cherry picked from commit 3685de750e6a091663a0abe42528cad29e960e35)
33
34Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8e03235147a9e774d3ba084e93c2da1aa94d1cec]
35CVE: CVE-2021-20197
36Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
37---
38 binutils/ar.c | 2 +-
39 binutils/arsup.c | 2 +-
40 binutils/bucomm.h | 3 ++-
41 binutils/objcopy.c | 8 ++-----
42 binutils/rename.c | 55 +++++++++-------------------------------------
43 6 files changed, 29 insertions(+), 54 deletions(-)
44
45diff --git a/binutils/ar.c b/binutils/ar.c
46index 45a34e3a6cf..3a91708b51c 100644
47--- a/binutils/ar.c
48+++ b/binutils/ar.c
49@@ -1308,7 +1308,7 @@ write_archive (bfd *iarch)
50 /* We don't care if this fails; we might be creating the archive. */
51 bfd_close (iarch);
52
53- if (smart_rename (new_name, old_name, 0) != 0)
54+ if (smart_rename (new_name, old_name, NULL) != 0)
55 xexit (1);
56 free (old_name);
57 free (new_name);
58diff --git a/binutils/arsup.c b/binutils/arsup.c
59index 5403a0c5d74..0a1f63f6456 100644
60--- a/binutils/arsup.c
61+++ b/binutils/arsup.c
62@@ -351,7 +351,7 @@ ar_save (void)
63
64 bfd_close (obfd);
65
66- smart_rename (ofilename, real_name, 0);
67+ smart_rename (ofilename, real_name, NULL);
68 obfd = 0;
69 free (ofilename);
70 }
71diff --git a/binutils/bucomm.h b/binutils/bucomm.h
72index 91f6a5b228f..aa7e33d8cd1 100644
73--- a/binutils/bucomm.h
74+++ b/binutils/bucomm.h
75@@ -71,7 +71,8 @@ extern void print_version (const char *);
76 /* In rename.c. */
77 extern void set_times (const char *, const struct stat *);
78
79-extern int smart_rename (const char *, const char *, int);
80+extern int smart_rename (const char *, const char *, struct stat *);
81+
82
83 /* In libiberty. */
84 void *xmalloc (size_t);
85diff --git a/binutils/objcopy.c b/binutils/objcopy.c
86index eab3b6db585..07a872b5a80 100644
87--- a/binutils/objcopy.c
88+++ b/binutils/objcopy.c
89@@ -4861,12 +4861,10 @@ strip_main (int argc, char *argv[])
90 output_target, NULL);
91 if (status == 0)
92 {
93- if (preserve_dates)
94- set_times (tmpname, &statbuf);
95 if (output_file != tmpname)
96 status = (smart_rename (tmpname,
97 output_file ? output_file : argv[i],
98- preserve_dates) != 0);
99+ preserve_dates ? &statbuf : NULL) != 0);
100 if (status == 0)
101 status = hold_status;
102 }
103@@ -5931,11 +5929,9 @@ copy_main (int argc, char *argv[])
104 output_target, input_arch);
105 if (status == 0)
106 {
107- if (preserve_dates)
108- set_times (tmpname, &statbuf);
109 if (tmpname != output_filename)
110 status = (smart_rename (tmpname, input_filename,
111- preserve_dates) != 0);
112+ preserve_dates ? &statbuf : NULL) != 0);
113 }
114 else
115 unlink_if_ordinary (tmpname);
116diff --git a/binutils/rename.c b/binutils/rename.c
117index 65ad5bf52c4..f471b45fd3f 100644
118--- a/binutils/rename.c
119+++ b/binutils/rename.c
120@@ -122,20 +122,13 @@ set_times (const char *destination, const struct stat *statbuf)
121 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
122 }
123
124-#ifndef S_ISLNK
125-#ifdef S_IFLNK
126-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
127-#else
128-#define S_ISLNK(m) 0
129-#define lstat stat
130-#endif
131-#endif
132-
133-/* Rename FROM to TO, copying if TO is a link.
134- Return 0 if ok, -1 if error. */
135+/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status
136+ that, if non-NULL, is used to fix up timestamps after rename. Return 0 if
137+ ok, -1 if error. */
138
139 int
140-smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED)
141+smart_rename (const char *from, const char *to,
142+ struct stat *target_stat ATTRIBUTE_UNUSED)
143 {
144 bfd_boolean exists;
145 struct stat s;
146@@ -158,38 +151,10 @@ smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNU
147 unlink (from);
148 }
149 #else
150- /* Use rename only if TO is not a symbolic link and has
151- only one hard link, and we have permission to write to it. */
152- if (! exists
153- || (!S_ISLNK (s.st_mode)
154- && S_ISREG (s.st_mode)
155- && (s.st_mode & S_IWUSR)
156- && s.st_nlink == 1)
157- )
158+ /* Avoid a full copy and use rename if TO does not exist. */
159+ if (!exists)
160 {
161- ret = rename (from, to);
162- if (ret == 0)
163- {
164- if (exists)
165- {
166- /* Try to preserve the permission bits and ownership of
167- TO. First get the mode right except for the setuid
168- bit. Then change the ownership. Then fix the setuid
169- bit. We do the chmod before the chown because if the
170- chown succeeds, and we are a normal user, we won't be
171- able to do the chmod afterward. We don't bother to
172- fix the setuid bit first because that might introduce
173- a fleeting security problem, and because the chown
174- will clear the setuid bit anyhow. We only fix the
175- setuid bit if the chown succeeds, because we don't
176- want to introduce an unexpected setuid file owned by
177- the user running objcopy. */
178- chmod (to, s.st_mode & 0777);
179- if (chown (to, s.st_uid, s.st_gid) >= 0)
180- chmod (to, s.st_mode & 07777);
181- }
182- }
183- else
184+ if ((ret = rename (from, to)) != 0)
185 {
186 /* We have to clean up here. */
187 non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
188@@ -202,8 +167,8 @@ smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNU
189 if (ret != 0)
190 non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno));
191
192- if (preserve_dates)
193- set_times (to, &s);
194+ if (target_stat != NULL)
195+ set_times (to, target_stat);
196 unlink (from);
197 }
198 #endif /* _WIN32 && !__CYGWIN32__ */
199--
2002.31.1
201
diff --git a/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-42574.patch b/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-42574.patch
new file mode 100644
index 0000000000..6adc438b5c
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-42574.patch
@@ -0,0 +1,2006 @@
1From b3aa80b45c4f46029efeb204bb9f2d2c4278a0e5 Mon Sep 17 00:00:00 2001
2From: Nick Clifton <nickc@redhat.com>
3Date: Tue, 9 Nov 2021 13:25:42 +0000
4Subject: [PATCH] Add --unicode option to control how unicode characters are
5 handled by display tools.
6
7 * nm.c: Add --unicode option to control how unicode characters are
8 handled.
9 * objdump.c: Likewise.
10 * readelf.c: Likewise.
11 * strings.c: Likewise.
12 * binutils.texi: Document the new feature.
13 * NEWS: Document the new feature.
14 * testsuite/binutils-all/unicode.exp: New file.
15 * testsuite/binutils-all/nm.hex.unicode
16 * testsuite/binutils-all/strings.escape.unicode
17 * testsuite/binutils-all/objdump.highlight.unicode
18 * testsuite/binutils-all/readelf.invalid.unicode
19
20CVE: CVE-2021-42574
21Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=b3aa80b45c4f46029efeb204bb9f2d2c4278a0e5]
22
23Signed-off-by: pgowda <pgowda.cve@gmail.com>
24---
25 binutils/ChangeLog | 15 +
26 binutils/NEWS | 9 +
27 binutils/doc/binutils.texi | 78 ++++
28 binutils/nm.c | 228 ++++++++++-
29 binutils/objdump.c | 235 ++++++++++--
30 binutils/readelf.c | 190 +++++++++-
31 binutils/strings.c | 757 ++++++++++++++++++++++++++++++++++---
32 7 files changed, 1409 insertions(+), 103 deletions(-)
33
34diff --git a/binutils/ChangeLog b/binutils/ChangeLog
35--- a/binutils/ChangeLog 2021-12-23 03:23:38.425843662 -0800
36+++ b/binutils/ChangeLog 2021-12-23 03:30:31.094968942 -0800
37@@ -1,3 +1,18 @@
38+2021-11-09 Nick Clifton <nickc@redhat.com>
39+
40+ * nm.c: Add --unicode option to control how unicode characters are
41+ handled.
42+ * objdump.c: Likewise.
43+ * readelf.c: Likewise.
44+ * strings.c: Likewise.
45+ * binutils.texi: Document the new feature.
46+ * NEWS: Document the new feature.
47+ * testsuite/binutils-all/unicode.exp: New file.
48+ * testsuite/binutils-all/nm.hex.unicode
49+ * testsuite/binutils-all/strings.escape.unicode
50+ * testsuite/binutils-all/objdump.highlight.unicode
51+ * testsuite/binutils-all/readelf.invalid.unicode
52+
53 2021-04-15 Alan Modra <amodra@gmail.com>
54
55 PR 27456
56diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
57--- a/binutils/doc/binutils.texi 2021-12-23 03:23:38.441843395 -0800
58+++ b/binutils/doc/binutils.texi 2021-12-23 03:30:31.094968942 -0800
59@@ -805,6 +805,7 @@ nm [@option{-A}|@option{-o}|@option{--pr
60 [@option{-s}|@option{--print-armap}] [@option{-t} @var{radix}|@option{--radix=}@var{radix}]
61 [@option{-u}|@option{--undefined-only}] [@option{-V}|@option{--version}]
62 [@option{-X 32_64}] [@option{--defined-only}] [@option{--no-demangle}]
63+ [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
64 [@option{--plugin} @var{name}]
65 [@option{--no-recurse-limit}|@option{--recurse-limit}]]
66 [@option{--size-sort}] [@option{--special-syms}]
67@@ -1114,6 +1115,21 @@ Use @var{radix} as the radix for printin
68 @cindex undefined symbols
69 Display only undefined symbols (those external to each object file).
70
71+@item -U @var{[d|i|l|e|x|h]}
72+@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
73+Controls the display of UTF-8 encoded mulibyte characters in strings.
74+The default (@option{--unicode=default}) is to give them no special
75+treatment. The @option{--unicode=locale} option displays the sequence
76+in the current locale, which may or may not support them. The options
77+@option{--unicode=hex} and @option{--unicode=invalid} display them as
78+hex byte sequences enclosed by either angle brackets or curly braces.
79+
80+The @option{--unicode=escape} option displays them as escape sequences
81+(@var{\uxxxx}) and the @option{--unicode=highlight} option displays
82+them as escape sequences highlighted in red (if supported by the
83+output device). The colouring is intended to draw attention to the
84+presence of unicode sequences where they might not be expected.
85+
86 @item -V
87 @itemx --version
88 Show the version number of @command{nm} and exit.
89@@ -2210,6 +2226,7 @@ objdump [@option{-a}|@option{--archive-h
90 [@option{--prefix-strip=}@var{level}]
91 [@option{--insn-width=}@var{width}]
92 [@option{--visualize-jumps[=color|=extended-color|=off]}
93+ [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
94 [@option{-V}|@option{--version}]
95 [@option{-H}|@option{--help}]
96 @var{objfile}@dots{}
97@@ -2877,6 +2894,21 @@ When displaying symbols include those wh
98 special in some way and which would not normally be of interest to the
99 user.
100
101+@item -U @var{[d|i|l|e|x|h]}
102+@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
103+Controls the display of UTF-8 encoded mulibyte characters in strings.
104+The default (@option{--unicode=default}) is to give them no special
105+treatment. The @option{--unicode=locale} option displays the sequence
106+in the current locale, which may or may not support them. The options
107+@option{--unicode=hex} and @option{--unicode=invalid} display them as
108+hex byte sequences enclosed by either angle brackets or curly braces.
109+
110+The @option{--unicode=escape} option displays them as escape sequences
111+(@var{\uxxxx}) and the @option{--unicode=highlight} option displays
112+them as escape sequences highlighted in red (if supported by the
113+output device). The colouring is intended to draw attention to the
114+presence of unicode sequences where they might not be expected.
115+
116 @item -V
117 @itemx --version
118 Print the version number of @command{objdump} and exit.
119@@ -3153,6 +3185,7 @@ strings [@option{-afovV}] [@option{-}@va
120 [@option{-n} @var{min-len}] [@option{--bytes=}@var{min-len}]
121 [@option{-t} @var{radix}] [@option{--radix=}@var{radix}]
122 [@option{-e} @var{encoding}] [@option{--encoding=}@var{encoding}]
123+ [@option{-U} @var{method}] [@option{--unicode=}@var{method}]
124 [@option{-}] [@option{--all}] [@option{--print-file-name}]
125 [@option{-T} @var{bfdname}] [@option{--target=}@var{bfdname}]
126 [@option{-w}] [@option{--include-all-whitespace}]
127@@ -3244,6 +3277,28 @@ single-8-bit-byte characters, @samp{b} =
128 littleendian. Useful for finding wide character strings. (@samp{l}
129 and @samp{b} apply to, for example, Unicode UTF-16/UCS-2 encodings).
130
131+@item -U @var{[d|i|l|e|x|h]}
132+@itemx --unicode=@var{[default|invalid|locale|escape|hex|highlight]}
133+Controls the display of UTF-8 encoded mulibyte characters in strings.
134+The default (@option{--unicode=default}) is to give them no special
135+treatment, and instead rely upon the setting of the
136+@option{--encoding} option. The other values for this option
137+automatically enable @option{--encoding=S}.
138+
139+The @option{--unicode=invalid} option treats them as non-graphic
140+characters and hence not part of a valid string. All the remaining
141+options treat them as valid string characters.
142+
143+The @option{--unicode=locale} option displays them in the current
144+locale, which may or may not support UTF-8 encoding. The
145+@option{--unicode=hex} option displays them as hex byte sequences
146+enclosed between @var{<>} characters. The @option{--unicode=escape}
147+option displays them as escape sequences (@var{\uxxxx}) and the
148+@option{--unicode=highlight} option displays them as escape sequences
149+highlighted in red (if supported by the output device). The colouring
150+is intended to draw attention to the presence of unicode sequences
151+where they might not be expected.
152+
153 @item -T @var{bfdname}
154 @itemx --target=@var{bfdname}
155 @cindex object code format
156@@ -4740,6 +4795,7 @@ readelf [@option{-a}|@option{--all}]
157 [@option{--dyn-syms}|@option{--lto-syms}]
158 [@option{--demangle@var{=style}}|@option{--no-demangle}]
159 [@option{--recurse-limit}|@option{--no-recurse-limit}]
160+ [@option{-U} @var{method}|@option{--unicode=}@var{method}]
161 [@option{-n}|@option{--notes}]
162 [@option{-r}|@option{--relocs}]
163 [@option{-u}|@option{--unwind}]
164@@ -4887,6 +4943,28 @@ necessary in order to demangle truly com
165 that if the recursion limit is disabled then stack exhaustion is
166 possible and any bug reports about such an event will be rejected.
167
168+@item -U @var{[d|i|l|e|x|h]}
169+@itemx --unicode=[default|invalid|locale|escape|hex|highlight]
170+Controls the display of non-ASCII characters in identifier names.
171+The default (@option{--unicode=locale} or @option{--unicode=default}) is
172+to treat them as multibyte characters and display them in the current
173+locale. All other versions of this option treat the bytes as UTF-8
174+encoded values and attempt to interpret them. If they cannot be
175+interpreted or if the @option{--unicode=invalid} option is used then
176+they are displayed as a sequence of hex bytes, encloses in curly
177+parethesis characters.
178+
179+Using the @option{--unicode=escape} option will display the characters
180+as as unicode escape sequences (@var{\uxxxx}). Using the
181+@option{--unicode=hex} will display the characters as hex byte
182+sequences enclosed between angle brackets.
183+
184+Using the @option{--unicode=highlight} will display the characters as
185+unicode escape sequences but it will also highlighted them in red,
186+assuming that colouring is supported by the output device. The
187+colouring is intended to draw attention to the presence of unicode
188+sequences when they might not be expected.
189+
190 @item -e
191 @itemx --headers
192 Display all the headers in the file. Equivalent to @option{-h -l -S}.
193diff --git a/binutils/NEWS b/binutils/NEWS
194--- a/binutils/NEWS 2021-12-23 03:23:38.433843528 -0800
195+++ b/binutils/NEWS 2021-12-23 03:30:31.094968942 -0800
196@@ -1,5 +1,14 @@
197 -*- text -*-
198
199+* Tools which display symbols or strings (readelf, strings, nm, objdump)
200+ have a new command line option which controls how unicode characters are
201+ handled. By default they are treated as normal for the tool. Using
202+ --unicode=locale will display them according to the current locale.
203+ Using --unicode=hex will display them as hex byte values, whilst
204+ --unicode=escape will display them as escape sequences. In addition
205+ using --unicode=highlight will display them as unicode escape sequences
206+ highlighted in red (if supported by the output device).
207+
208 Changes in 2.36:
209
210 * Update elfedit and readelf with LAM_U48 and LAM_U57 support.
211diff --git a/binutils/nm.c b/binutils/nm.c
212--- a/binutils/nm.c 2021-12-23 03:23:38.441843395 -0800
213+++ b/binutils/nm.c 2021-12-23 03:30:31.098968875 -0800
214@@ -38,6 +38,11 @@
215 #include "bucomm.h"
216 #include "plugin-api.h"
217 #include "plugin.h"
218+#include "safe-ctype.h"
219+
220+#ifndef streq
221+#define streq(a,b) (strcmp ((a),(b)) == 0)
222+#endif
223
224 /* When sorting by size, we use this structure to hold the size and a
225 pointer to the minisymbol. */
226@@ -192,6 +197,18 @@ static const char *plugin_target = NULL;
227 static bfd *lineno_cache_bfd;
228 static bfd *lineno_cache_rel_bfd;
229
230+typedef enum unicode_display_type
231+{
232+ unicode_default = 0,
233+ unicode_locale,
234+ unicode_escape,
235+ unicode_hex,
236+ unicode_highlight,
237+ unicode_invalid
238+} unicode_display_type;
239+
240+static unicode_display_type unicode_display = unicode_default;
241+
242 enum long_option_values
243 {
244 OPTION_TARGET = 200,
245@@ -234,6 +251,7 @@ static struct option long_options[] =
246 {"target", required_argument, 0, OPTION_TARGET},
247 {"defined-only", no_argument, &defined_only, 1},
248 {"undefined-only", no_argument, &undefined_only, 1},
249+ {"unicode", required_argument, NULL, 'U'},
250 {"version", no_argument, &show_version, 1},
251 {"with-symbol-versions", no_argument, NULL,
252 OPTION_WITH_SYMBOL_VERSIONS},
253@@ -285,6 +303,8 @@ usage (FILE *stream, int status)
254 -t, --radix=RADIX Use RADIX for printing symbol values\n\
255 --target=BFDNAME Specify the target object format as BFDNAME\n\
256 -u, --undefined-only Display only undefined symbols\n\
257+ -U {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\
258+ --unicode={default|show|invalid|hex|escape|highlight}\n\
259 --with-symbol-versions Display version strings after symbol names\n\
260 -X 32_64 (ignored)\n\
261 @FILE Read options from FILE\n\
262@@ -399,6 +419,188 @@ get_coff_symbol_type (const struct inter
263 fatal ("%s", xstrerror (errno));
264 return bufp;
265 }
266+
267+/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
268+ The conversion format is controlled by the unicode_display variable.
269+ Returns the number of characters added to OUT.
270+ Returns the number of bytes consumed from IN in CONSUMED.
271+ Always consumes at least one byte and displays at least one character. */
272+
273+static unsigned int
274+display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
275+{
276+ char * orig_out = out;
277+ unsigned int nchars = 0;
278+ unsigned int j;
279+
280+ if (unicode_display == unicode_default)
281+ goto invalid;
282+
283+ if (in[0] < 0xc0)
284+ goto invalid;
285+
286+ if ((in[1] & 0xc0) != 0x80)
287+ goto invalid;
288+
289+ if ((in[0] & 0x20) == 0)
290+ {
291+ nchars = 2;
292+ goto valid;
293+ }
294+
295+ if ((in[2] & 0xc0) != 0x80)
296+ goto invalid;
297+
298+ if ((in[0] & 0x10) == 0)
299+ {
300+ nchars = 3;
301+ goto valid;
302+ }
303+
304+ if ((in[3] & 0xc0) != 0x80)
305+ goto invalid;
306+
307+ nchars = 4;
308+
309+ valid:
310+ switch (unicode_display)
311+ {
312+ case unicode_locale:
313+ /* Copy the bytes into the output buffer as is. */
314+ memcpy (out, in, nchars);
315+ out += nchars;
316+ break;
317+
318+ case unicode_invalid:
319+ case unicode_hex:
320+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
321+ out += sprintf (out, "0x");
322+ for (j = 0; j < nchars; j++)
323+ out += sprintf (out, "%02x", in [j]);
324+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
325+ break;
326+
327+ case unicode_highlight:
328+ if (isatty (1))
329+ out += sprintf (out, "\x1B[31;47m"); /* Red. */
330+ /* Fall through. */
331+ case unicode_escape:
332+ switch (nchars)
333+ {
334+ case 2:
335+ out += sprintf (out, "\\u%02x%02x",
336+ ((in[0] & 0x1c) >> 2),
337+ ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
338+ break;
339+
340+ case 3:
341+ out += sprintf (out, "\\u%02x%02x",
342+ ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
343+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
344+ break;
345+
346+ case 4:
347+ out += sprintf (out, "\\u%02x%02x%02x",
348+ ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
349+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
350+ ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
351+ break;
352+ default:
353+ /* URG. */
354+ break;
355+ }
356+
357+ if (unicode_display == unicode_highlight && isatty (1))
358+ out += sprintf (out, "\033[0m"); /* Default colour. */
359+ break;
360+
361+ default:
362+ /* URG */
363+ break;
364+ }
365+
366+ * consumed = nchars;
367+ return out - orig_out;
368+
369+ invalid:
370+ /* Not a valid UTF-8 sequence. */
371+ *out = *in;
372+ * consumed = 1;
373+ return 1;
374+}
375+
376+/* Convert any UTF-8 encoded characters in NAME into the form specified by
377+ unicode_display. Also converts control characters. Returns a static
378+ buffer if conversion was necessary.
379+ Code stolen from objdump.c:sanitize_string(). */
380+
381+static const char *
382+convert_utf8 (const char * in)
383+{
384+ static char * buffer = NULL;
385+ static size_t buffer_len = 0;
386+ const char * original = in;
387+ char * out;
388+
389+ /* Paranoia. */
390+ if (in == NULL)
391+ return "";
392+
393+ /* See if any conversion is necessary.
394+ In the majority of cases it will not be needed. */
395+ do
396+ {
397+ unsigned char c = *in++;
398+
399+ if (c == 0)
400+ return original;
401+
402+ if (ISCNTRL (c))
403+ break;
404+
405+ if (unicode_display != unicode_default && c >= 0xc0)
406+ break;
407+ }
408+ while (1);
409+
410+ /* Copy the input, translating as needed. */
411+ in = original;
412+ if (buffer_len < (strlen (in) * 9))
413+ {
414+ free ((void *) buffer);
415+ buffer_len = strlen (in) * 9;
416+ buffer = xmalloc (buffer_len + 1);
417+ }
418+
419+ out = buffer;
420+ do
421+ {
422+ unsigned char c = *in++;
423+
424+ if (c == 0)
425+ break;
426+
427+ if (ISCNTRL (c))
428+ {
429+ *out++ = '^';
430+ *out++ = c + 0x40;
431+ }
432+ else if (unicode_display != unicode_default && c >= 0xc0)
433+ {
434+ unsigned int num_consumed;
435+
436+ out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
437+ in += num_consumed - 1;
438+ }
439+ else
440+ *out++ = c;
441+ }
442+ while (1);
443+
444+ *out = 0;
445+ return buffer;
446+}
447+
448
449 /* Print symbol name NAME, read from ABFD, with printf format FORM,
450 demangling it if requested. */
451@@ -418,6 +620,11 @@ print_symname (const char *form, struct
452 name = alloc;
453 }
454
455+ if (unicode_display != unicode_default)
456+ {
457+ name = convert_utf8 (name);
458+ }
459+
460 if (info != NULL && info->elfinfo)
461 {
462 const char *version_string;
463@@ -1738,7 +1945,7 @@ main (int argc, char **argv)
464 fatal (_("fatal error: libbfd ABI mismatch"));
465 set_default_bfd_target ();
466
467- while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uvVvX:",
468+ while ((c = getopt_long (argc, argv, "aABCDef:gHhlnopPrSst:uU:vVvX:",
469 long_options, (int *) 0)) != EOF)
470 {
471 switch (c)
472@@ -1828,6 +2035,24 @@ main (int argc, char **argv)
473 case 'u':
474 undefined_only = 1;
475 break;
476+
477+ case 'U':
478+ if (streq (optarg, "default") || streq (optarg, "d"))
479+ unicode_display = unicode_default;
480+ else if (streq (optarg, "locale") || streq (optarg, "l"))
481+ unicode_display = unicode_locale;
482+ else if (streq (optarg, "escape") || streq (optarg, "e"))
483+ unicode_display = unicode_escape;
484+ else if (streq (optarg, "invalid") || streq (optarg, "i"))
485+ unicode_display = unicode_invalid;
486+ else if (streq (optarg, "hex") || streq (optarg, "x"))
487+ unicode_display = unicode_hex;
488+ else if (streq (optarg, "highlight") || streq (optarg, "h"))
489+ unicode_display = unicode_highlight;
490+ else
491+ fatal (_("invalid argument to -U/--unicode: %s"), optarg);
492+ break;
493+
494 case 'V':
495 show_version = 1;
496 break;
497diff --git a/binutils/objdump.c b/binutils/objdump.c
498--- a/binutils/objdump.c 2021-12-23 03:23:38.445843329 -0800
499+++ b/binutils/objdump.c 2021-12-23 03:30:31.098968875 -0800
500@@ -205,6 +205,19 @@ static const struct objdump_private_desc
501
502 /* The list of detected jumps inside a function. */
503 static struct jump_info *detected_jumps = NULL;
504+
505+typedef enum unicode_display_type
506+{
507+ unicode_default = 0,
508+ unicode_locale,
509+ unicode_escape,
510+ unicode_hex,
511+ unicode_highlight,
512+ unicode_invalid
513+} unicode_display_type;
514+
515+static unicode_display_type unicode_display = unicode_default;
516+
517
518 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
519 static void
520@@ -274,6 +287,8 @@ usage (FILE *stream, int status)
521 --recurse-limit Enable a limit on recursion whilst demangling. [Default]\n\
522 --no-recurse-limit Disable a limit on recursion whilst demangling\n\
523 -w, --wide Format output for more than 80 columns\n\
524+ -U[d|l|i|x|e|h] Controls the display of UTF-8 unicode characters\n\
525+ --unicode=[default|locale|invalid|hex|escape|highlight]\n\
526 -z, --disassemble-zeroes Do not skip blocks of zeroes when disassembling\n\
527 --start-address=ADDR Only process data whose address is >= ADDR\n\
528 --stop-address=ADDR Only process data whose address is < ADDR\n\
529@@ -348,17 +363,23 @@ static struct option long_options[]=
530 {
531 {"adjust-vma", required_argument, NULL, OPTION_ADJUST_VMA},
532 {"all-headers", no_argument, NULL, 'x'},
533- {"private-headers", no_argument, NULL, 'p'},
534- {"private", required_argument, NULL, 'P'},
535 {"architecture", required_argument, NULL, 'm'},
536 {"archive-headers", no_argument, NULL, 'a'},
537+#ifdef ENABLE_LIBCTF
538+ {"ctf", required_argument, NULL, OPTION_CTF},
539+ {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
540+#endif
541 {"debugging", no_argument, NULL, 'g'},
542 {"debugging-tags", no_argument, NULL, 'e'},
543 {"demangle", optional_argument, NULL, 'C'},
544 {"disassemble", optional_argument, NULL, 'd'},
545 {"disassemble-all", no_argument, NULL, 'D'},
546- {"disassembler-options", required_argument, NULL, 'M'},
547 {"disassemble-zeroes", no_argument, NULL, 'z'},
548+ {"disassembler-options", required_argument, NULL, 'M'},
549+ {"dwarf", optional_argument, NULL, OPTION_DWARF},
550+ {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
551+ {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
552+ {"dwarf-start", required_argument, 0, OPTION_DWARF_START},
553 {"dynamic-reloc", no_argument, NULL, 'R'},
554 {"dynamic-syms", no_argument, NULL, 'T'},
555 {"endian", required_argument, NULL, OPTION_ENDIAN},
556@@ -368,15 +389,22 @@ static struct option long_options[]=
557 {"full-contents", no_argument, NULL, 's'},
558 {"headers", no_argument, NULL, 'h'},
559 {"help", no_argument, NULL, 'H'},
560+ {"include", required_argument, NULL, 'I'},
561 {"info", no_argument, NULL, 'i'},
562+ {"inlines", no_argument, 0, OPTION_INLINES},
563+ {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
564 {"line-numbers", no_argument, NULL, 'l'},
565- {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
566 {"no-addresses", no_argument, &no_addresses, 1},
567+ {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
568+ {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
569+ {"no-show-raw-insn", no_argument, &show_raw_insn, -1},
570+ {"prefix", required_argument, NULL, OPTION_PREFIX},
571 {"prefix-addresses", no_argument, &prefix_addresses, 1},
572+ {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
573+ {"private", required_argument, NULL, 'P'},
574+ {"private-headers", no_argument, NULL, 'p'},
575 {"recurse-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
576 {"recursion-limit", no_argument, NULL, OPTION_RECURSE_LIMIT},
577- {"no-recurse-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
578- {"no-recursion-limit", no_argument, NULL, OPTION_NO_RECURSE_LIMIT},
579 {"reloc", no_argument, NULL, 'r'},
580 {"section", required_argument, NULL, 'j'},
581 {"section-headers", no_argument, NULL, 'h'},
582@@ -384,28 +412,16 @@ static struct option long_options[]=
583 {"source", no_argument, NULL, 'S'},
584 {"source-comment", optional_argument, NULL, OPTION_SOURCE_COMMENT},
585 {"special-syms", no_argument, &dump_special_syms, 1},
586- {"include", required_argument, NULL, 'I'},
587- {"dwarf", optional_argument, NULL, OPTION_DWARF},
588-#ifdef ENABLE_LIBCTF
589- {"ctf", required_argument, NULL, OPTION_CTF},
590- {"ctf-parent", required_argument, NULL, OPTION_CTF_PARENT},
591-#endif
592 {"stabs", no_argument, NULL, 'G'},
593 {"start-address", required_argument, NULL, OPTION_START_ADDRESS},
594 {"stop-address", required_argument, NULL, OPTION_STOP_ADDRESS},
595 {"syms", no_argument, NULL, 't'},
596 {"target", required_argument, NULL, 'b'},
597+ {"unicode", required_argument, NULL, 'U'},
598 {"version", no_argument, NULL, 'V'},
599- {"wide", no_argument, NULL, 'w'},
600- {"prefix", required_argument, NULL, OPTION_PREFIX},
601- {"prefix-strip", required_argument, NULL, OPTION_PREFIX_STRIP},
602- {"insn-width", required_argument, NULL, OPTION_INSN_WIDTH},
603- {"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
604- {"dwarf-start", required_argument, 0, OPTION_DWARF_START},
605- {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
606- {"inlines", no_argument, 0, OPTION_INLINES},
607 {"visualize-jumps", optional_argument, 0, OPTION_VISUALIZE_JUMPS},
608- {0, no_argument, 0, 0}
609+ {"wide", no_argument, NULL, 'w'},
610+ {NULL, no_argument, NULL, 0}
611 };
612
613 static void
614@@ -415,9 +431,121 @@ nonfatal (const char *msg)
615 exit_status = 1;
616 }
617
618+/* Convert a potential UTF-8 encoded sequence in IN into characters in OUT.
619+ The conversion format is controlled by the unicode_display variable.
620+ Returns the number of characters added to OUT.
621+ Returns the number of bytes consumed from IN in CONSUMED.
622+ Always consumes at least one byte and displays at least one character. */
623+
624+static unsigned int
625+display_utf8 (const unsigned char * in, char * out, unsigned int * consumed)
626+{
627+ char * orig_out = out;
628+ unsigned int nchars = 0;
629+ unsigned int j;
630+
631+ if (unicode_display == unicode_default)
632+ goto invalid;
633+
634+ if (in[0] < 0xc0)
635+ goto invalid;
636+
637+ if ((in[1] & 0xc0) != 0x80)
638+ goto invalid;
639+
640+ if ((in[0] & 0x20) == 0)
641+ {
642+ nchars = 2;
643+ goto valid;
644+ }
645+
646+ if ((in[2] & 0xc0) != 0x80)
647+ goto invalid;
648+
649+ if ((in[0] & 0x10) == 0)
650+ {
651+ nchars = 3;
652+ goto valid;
653+ }
654+
655+ if ((in[3] & 0xc0) != 0x80)
656+ goto invalid;
657+
658+ nchars = 4;
659+
660+ valid:
661+ switch (unicode_display)
662+ {
663+ case unicode_locale:
664+ /* Copy the bytes into the output buffer as is. */
665+ memcpy (out, in, nchars);
666+ out += nchars;
667+ break;
668+
669+ case unicode_invalid:
670+ case unicode_hex:
671+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '<' : '{');
672+ out += sprintf (out, "0x");
673+ for (j = 0; j < nchars; j++)
674+ out += sprintf (out, "%02x", in [j]);
675+ out += sprintf (out, "%c", unicode_display == unicode_hex ? '>' : '}');
676+ break;
677+
678+ case unicode_highlight:
679+ if (isatty (1))
680+ out += sprintf (out, "\x1B[31;47m"); /* Red. */
681+ /* Fall through. */
682+ case unicode_escape:
683+ switch (nchars)
684+ {
685+ case 2:
686+ out += sprintf (out, "\\u%02x%02x",
687+ ((in[0] & 0x1c) >> 2),
688+ ((in[0] & 0x03) << 6) | (in[1] & 0x3f));
689+ break;
690+
691+ case 3:
692+ out += sprintf (out, "\\u%02x%02x",
693+ ((in[0] & 0x0f) << 4) | ((in[1] & 0x3c) >> 2),
694+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3f)));
695+ break;
696+
697+ case 4:
698+ out += sprintf (out, "\\u%02x%02x%02x",
699+ ((in[0] & 0x07) << 6) | ((in[1] & 0x3c) >> 2),
700+ ((in[1] & 0x03) << 6) | ((in[2] & 0x3c) >> 2),
701+ ((in[2] & 0x03) << 6) | ((in[3] & 0x3f)));
702+ break;
703+ default:
704+ /* URG. */
705+ break;
706+ }
707+
708+ if (unicode_display == unicode_highlight && isatty (1))
709+ out += sprintf (out, "\033[0m"); /* Default colour. */
710+ break;
711+
712+ default:
713+ /* URG */
714+ break;
715+ }
716+
717+ * consumed = nchars;
718+ return out - orig_out;
719+
720+ invalid:
721+ /* Not a valid UTF-8 sequence. */
722+ *out = *in;
723+ * consumed = 1;
724+ return 1;
725+}
726+
727 /* Returns a version of IN with any control characters
728 replaced by escape sequences. Uses a static buffer
729- if necessary. */
730+ if necessary.
731+
732+ If unicode display is enabled, then also handles the
733+ conversion of unicode characters. */
734
735 static const char *
736 sanitize_string (const char * in)
737@@ -435,40 +563,50 @@ sanitize_string (const char * in)
738 of cases it will not be needed. */
739 do
740 {
741- char c = *in++;
742+ unsigned char c = *in++;
743
744 if (c == 0)
745 return original;
746
747 if (ISCNTRL (c))
748 break;
749+
750+ if (unicode_display != unicode_default && c >= 0xc0)
751+ break;
752 }
753 while (1);
754
755 /* Copy the input, translating as needed. */
756 in = original;
757- if (buffer_len < (strlen (in) * 2))
758+ if (buffer_len < (strlen (in) * 9))
759 {
760 free ((void *) buffer);
761- buffer_len = strlen (in) * 2;
762+ buffer_len = strlen (in) * 9;
763 buffer = xmalloc (buffer_len + 1);
764 }
765
766 out = buffer;
767 do
768 {
769- char c = *in++;
770+ unsigned char c = *in++;
771
772 if (c == 0)
773 break;
774
775- if (!ISCNTRL (c))
776- *out++ = c;
777- else
778+ if (ISCNTRL (c))
779 {
780 *out++ = '^';
781 *out++ = c + 0x40;
782 }
783+ else if (unicode_display != unicode_default && c >= 0xc0)
784+ {
785+ unsigned int num_consumed;
786+
787+ out += display_utf8 ((const unsigned char *)(in - 1), out, & num_consumed);
788+ in += num_consumed - 1;
789+ }
790+ else
791+ *out++ = c;
792 }
793 while (1);
794
795@@ -4481,6 +4619,24 @@ dump_symbols (bfd *abfd ATTRIBUTE_UNUSED
796 free (alloc);
797 }
798 }
799+ else if (unicode_display != unicode_default
800+ && name != NULL && *name != '\0')
801+ {
802+ const char * sanitized_name;
803+
804+ /* If we want to sanitize the name, we do it here, and
805+ temporarily clobber it while calling bfd_print_symbol.
806+ FIXME: This is a gross hack. */
807+ sanitized_name = sanitize_string (name);
808+ if (sanitized_name != name)
809+ (*current)->name = sanitized_name;
810+ else
811+ sanitized_name = NULL;
812+ bfd_print_symbol (cur_bfd, stdout, *current,
813+ bfd_print_symbol_all);
814+ if (sanitized_name != NULL)
815+ (*current)->name = name;
816+ }
817 else
818 bfd_print_symbol (cur_bfd, stdout, *current,
819 bfd_print_symbol_all);
820@@ -5162,7 +5318,7 @@ main (int argc, char **argv)
821 set_default_bfd_target ();
822
823 while ((c = getopt_long (argc, argv,
824- "pP:ib:m:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
825+ "pP:ib:m:U:M:VvCdDlfFaHhrRtTxsSI:j:wE:zgeGW::",
826 long_options, (int *) 0))
827 != EOF)
828 {
829@@ -5441,6 +5597,23 @@ main (int argc, char **argv)
830 seenflag = TRUE;
831 break;
832
833+ case 'U':
834+ if (streq (optarg, "default") || streq (optarg, "d"))
835+ unicode_display = unicode_default;
836+ else if (streq (optarg, "locale") || streq (optarg, "l"))
837+ unicode_display = unicode_locale;
838+ else if (streq (optarg, "escape") || streq (optarg, "e"))
839+ unicode_display = unicode_escape;
840+ else if (streq (optarg, "invalid") || streq (optarg, "i"))
841+ unicode_display = unicode_invalid;
842+ else if (streq (optarg, "hex") || streq (optarg, "x"))
843+ unicode_display = unicode_hex;
844+ else if (streq (optarg, "highlight") || streq (optarg, "h"))
845+ unicode_display = unicode_highlight;
846+ else
847+ fatal (_("invalid argument to -U/--unicode: %s"), optarg);
848+ break;
849+
850 case 'H':
851 usage (stdout, 0);
852 /* No need to set seenflag or to break - usage() does not return. */
853diff --git a/binutils/readelf.c b/binutils/readelf.c
854--- a/binutils/readelf.c 2021-12-23 03:23:42.065783023 -0800
855+++ b/binutils/readelf.c 2021-12-23 03:30:36.582877519 -0800
856@@ -321,6 +321,19 @@ typedef enum print_mode
857 }
858 print_mode;
859
860+typedef enum unicode_display_type
861+{
862+ unicode_default = 0,
863+ unicode_locale,
864+ unicode_escape,
865+ unicode_hex,
866+ unicode_highlight,
867+ unicode_invalid
868+} unicode_display_type;
869+
870+static unicode_display_type unicode_display = unicode_default;
871+
872+
873 /* Versioned symbol info. */
874 enum versioned_symbol_info
875 {
876@@ -613,11 +626,18 @@ print_symbol (signed int width, const ch
877 if (c == 0)
878 break;
879
880- /* Do not print control characters directly as they can affect terminal
881- settings. Such characters usually appear in the names generated
882- by the assembler for local labels. */
883- if (ISCNTRL (c))
884+ if (ISPRINT (c))
885+ {
886+ putchar (c);
887+ width_remaining --;
888+ num_printed ++;
889+ }
890+ else if (ISCNTRL (c))
891 {
892+ /* Do not print control characters directly as they can affect terminal
893+ settings. Such characters usually appear in the names generated
894+ by the assembler for local labels. */
895+
896 if (width_remaining < 2)
897 break;
898
899@@ -625,11 +645,137 @@ print_symbol (signed int width, const ch
900 width_remaining -= 2;
901 num_printed += 2;
902 }
903- else if (ISPRINT (c))
904+ else if (c == 0x7f)
905 {
906- putchar (c);
907- width_remaining --;
908- num_printed ++;
909+ if (width_remaining < 5)
910+ break;
911+ printf ("<DEL>");
912+ width_remaining -= 5;
913+ num_printed += 5;
914+ }
915+ else if (unicode_display != unicode_locale
916+ && unicode_display != unicode_default)
917+ {
918+ /* Display unicode characters as something else. */
919+ unsigned char bytes[4];
920+ bfd_boolean is_utf8;
921+ unsigned int nbytes;
922+
923+ bytes[0] = c;
924+
925+ if (bytes[0] < 0xc0)
926+ {
927+ nbytes = 1;
928+ is_utf8 = FALSE;
929+ }
930+ else
931+ {
932+ bytes[1] = *symbol++;
933+
934+ if ((bytes[1] & 0xc0) != 0x80)
935+ {
936+ is_utf8 = FALSE;
937+ /* Do not consume this character. It may only
938+ be the first byte in the sequence that was
939+ corrupt. */
940+ --symbol;
941+ nbytes = 1;
942+ }
943+ else if ((bytes[0] & 0x20) == 0)
944+ {
945+ is_utf8 = TRUE;
946+ nbytes = 2;
947+ }
948+ else
949+ {
950+ bytes[2] = *symbol++;
951+
952+ if ((bytes[2] & 0xc0) != 0x80)
953+ {
954+ is_utf8 = FALSE;
955+ symbol -= 2;
956+ nbytes = 1;
957+ }
958+ else if ((bytes[0] & 0x10) == 0)
959+ {
960+ is_utf8 = TRUE;
961+ nbytes = 3;
962+ }
963+ else
964+ {
965+ bytes[3] = *symbol++;
966+
967+ nbytes = 4;
968+
969+ if ((bytes[3] & 0xc0) != 0x80)
970+ {
971+ is_utf8 = FALSE;
972+ symbol -= 3;
973+ nbytes = 1;
974+ }
975+ else
976+ is_utf8 = TRUE;
977+ }
978+ }
979+ }
980+
981+ if (unicode_display == unicode_invalid)
982+ is_utf8 = FALSE;
983+
984+ if (unicode_display == unicode_hex || ! is_utf8)
985+ {
986+ unsigned int i;
987+
988+ if (width_remaining < (nbytes * 2) + 2)
989+ break;
990+
991+ putchar (is_utf8 ? '<' : '{');
992+ printf ("0x");
993+ for (i = 0; i < nbytes; i++)
994+ printf ("%02x", bytes[i]);
995+ putchar (is_utf8 ? '>' : '}');
996+ }
997+ else
998+ {
999+ if (unicode_display == unicode_highlight && isatty (1))
1000+ printf ("\x1B[31;47m"); /* Red. */
1001+
1002+ switch (nbytes)
1003+ {
1004+ case 2:
1005+ if (width_remaining < 6)
1006+ break;
1007+ printf ("\\u%02x%02x",
1008+ (bytes[0] & 0x1c) >> 2,
1009+ ((bytes[0] & 0x03) << 6) | (bytes[1] & 0x3f));
1010+ break;
1011+ case 3:
1012+ if (width_remaining < 6)
1013+ break;
1014+ printf ("\\u%02x%02x",
1015+ ((bytes[0] & 0x0f) << 4) | ((bytes[1] & 0x3c) >> 2),
1016+ ((bytes[1] & 0x03) << 6) | (bytes[2] & 0x3f));
1017+ break;
1018+ case 4:
1019+ if (width_remaining < 8)
1020+ break;
1021+ printf ("\\u%02x%02x%02x",
1022+ ((bytes[0] & 0x07) << 6) | ((bytes[1] & 0x3c) >> 2),
1023+ ((bytes[1] & 0x03) << 6) | ((bytes[2] & 0x3c) >> 2),
1024+ ((bytes[2] & 0x03) << 6) | (bytes[3] & 0x3f));
1025+
1026+ break;
1027+ default:
1028+ /* URG. */
1029+ break;
1030+ }
1031+
1032+ if (unicode_display == unicode_highlight && isatty (1))
1033+ printf ("\033[0m"); /* Default colour. */
1034+ }
1035+
1036+ if (bytes[nbytes - 1] == 0)
1037+ break;
1038 }
1039 else
1040 {
1041@@ -4556,6 +4702,7 @@ static struct option options[] =
1042 {"syms", no_argument, 0, 's'},
1043 {"silent-truncation",no_argument, 0, 'T'},
1044 {"section-details", no_argument, 0, 't'},
1045+ {"unicode", required_argument, NULL, 'U'},
1046 {"unwind", no_argument, 0, 'u'},
1047 {"version-info", no_argument, 0, 'V'},
1048 {"version", no_argument, 0, 'v'},
1049@@ -4609,6 +4756,11 @@ usage (FILE * stream)
1050 --no-demangle Do not demangle low-level symbol names. (This is the default)\n\
1051 --recurse-limit Enable a demangling recursion limit. (This is the default)\n\
1052 --no-recurse-limit Disable a demangling recursion limit\n\
1053+ -U[dlexhi] --unicode=[default|locale|escape|hex|highlight|invalid]\n\
1054+ Display unicode characters as determined by the current locale\n\
1055+ (default), escape sequences, \"<hex sequences>\", highlighted\n\
1056+ escape sequences, or treat them as invalid and display as\n\
1057+ \"{hex sequences}\"\n\
1058 -n --notes Display the core notes (if present)\n\
1059 -r --relocs Display the relocations (if present)\n\
1060 -u --unwind Display the unwind info (if present)\n\
1061@@ -4749,7 +4901,7 @@ parse_args (struct dump_data *dumpdata,
1062 usage (stderr);
1063
1064 while ((c = getopt_long
1065- (argc, argv, "ACDHILNR:STVWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
1066+ (argc, argv, "ACDHILNR:STU:VWacdeghi:lnp:rstuvw::x:z", options, NULL)) != EOF)
1067 {
1068 switch (c)
1069 {
1070@@ -4943,6 +5095,24 @@ parse_args (struct dump_data *dumpdata,
1071 case OPTION_WITH_SYMBOL_VERSIONS:
1072 /* Ignored for backward compatibility. */
1073 break;
1074+ case 'U':
1075+ if (optarg == NULL)
1076+ error (_("Missing arg to -U/--unicode")); /* Can this happen ? */
1077+ else if (streq (optarg, "default") || streq (optarg, "d"))
1078+ unicode_display = unicode_default;
1079+ else if (streq (optarg, "locale") || streq (optarg, "l"))
1080+ unicode_display = unicode_locale;
1081+ else if (streq (optarg, "escape") || streq (optarg, "e"))
1082+ unicode_display = unicode_escape;
1083+ else if (streq (optarg, "invalid") || streq (optarg, "i"))
1084+ unicode_display = unicode_invalid;
1085+ else if (streq (optarg, "hex") || streq (optarg, "x"))
1086+ unicode_display = unicode_hex;
1087+ else if (streq (optarg, "highlight") || streq (optarg, "h"))
1088+ unicode_display = unicode_highlight;
1089+ else
1090+ error (_("invalid argument to -U/--unicode: %s"), optarg);
1091+ break;
1092
1093 default:
1094 /* xgettext:c-format */
1095diff --git a/binutils/strings.c b/binutils/strings.c
1096--- a/binutils/strings.c 2021-12-23 03:23:38.485842662 -0800
1097+++ b/binutils/strings.c 2021-12-23 03:30:36.586877452 -0800
1098@@ -55,6 +55,19 @@
1099 -T {bfdname}
1100 Specify a non-default object file format.
1101
1102+ --unicode={default|locale|invalid|hex|escape|highlight}
1103+ -u {d|l|i|x|e|h}
1104+ Determine how to handle UTF-8 unicode characters. The default
1105+ is no special treatment. All other versions of this option
1106+ only apply if the encoding is valid and enabling the option
1107+ implies --encoding=S.
1108+ The 'locale' option displays the characters according to the
1109+ current locale. The 'invalid' option treats them as
1110+ non-string characters. The 'hex' option displays them as hex
1111+ byte sequences. The 'escape' option displays them as escape
1112+ sequences and the 'highlight' option displays them as
1113+ coloured escape sequences.
1114+
1115 --output-separator=sep_string
1116 -s sep_string String used to separate parsed strings in output.
1117 Default is newline.
1118@@ -76,6 +89,22 @@
1119 #include "safe-ctype.h"
1120 #include "bucomm.h"
1121
1122+#ifndef streq
1123+#define streq(a,b) (strcmp ((a),(b)) == 0)
1124+#endif
1125+
1126+typedef enum unicode_display_type
1127+{
1128+ unicode_default = 0,
1129+ unicode_locale,
1130+ unicode_escape,
1131+ unicode_hex,
1132+ unicode_highlight,
1133+ unicode_invalid
1134+} unicode_display_type;
1135+
1136+static unicode_display_type unicode_display = unicode_default;
1137+
1138 #define STRING_ISGRAPHIC(c) \
1139 ( (c) >= 0 \
1140 && (c) <= 255 \
1141@@ -94,7 +123,7 @@ extern int errno;
1142 static int address_radix;
1143
1144 /* Minimum length of sequence of graphic chars to trigger output. */
1145-static int string_min;
1146+static unsigned int string_min;
1147
1148 /* Whether or not we include all whitespace as a graphic char. */
1149 static bfd_boolean include_all_whitespace;
1150@@ -121,21 +150,22 @@ static char *output_separator;
1151 static struct option long_options[] =
1152 {
1153 {"all", no_argument, NULL, 'a'},
1154+ {"bytes", required_argument, NULL, 'n'},
1155 {"data", no_argument, NULL, 'd'},
1156+ {"encoding", required_argument, NULL, 'e'},
1157+ {"help", no_argument, NULL, 'h'},
1158+ {"include-all-whitespace", no_argument, NULL, 'w'},
1159+ {"output-separator", required_argument, NULL, 's'},
1160 {"print-file-name", no_argument, NULL, 'f'},
1161- {"bytes", required_argument, NULL, 'n'},
1162 {"radix", required_argument, NULL, 't'},
1163- {"include-all-whitespace", no_argument, NULL, 'w'},
1164- {"encoding", required_argument, NULL, 'e'},
1165 {"target", required_argument, NULL, 'T'},
1166- {"output-separator", required_argument, NULL, 's'},
1167- {"help", no_argument, NULL, 'h'},
1168+ {"unicode", required_argument, NULL, 'U'},
1169 {"version", no_argument, NULL, 'v'},
1170 {NULL, 0, NULL, 0}
1171 };
1172
1173 static bfd_boolean strings_file (char *);
1174-static void print_strings (const char *, FILE *, file_ptr, int, int, char *);
1175+static void print_strings (const char *, FILE *, file_ptr, int, char *);
1176 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
1177
1178 int main (int, char **);
1179@@ -173,7 +203,7 @@ main (int argc, char **argv)
1180 encoding = 's';
1181 output_separator = NULL;
1182
1183- while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:Vv0123456789",
1184+ while ((optc = getopt_long (argc, argv, "adfhHn:wot:e:T:s:U:Vv0123456789",
1185 long_options, (int *) 0)) != EOF)
1186 {
1187 switch (optc)
1188@@ -244,7 +274,24 @@ main (int argc, char **argv)
1189
1190 case 's':
1191 output_separator = optarg;
1192- break;
1193+ break;
1194+
1195+ case 'U':
1196+ if (streq (optarg, "default") || streq (optarg, "d"))
1197+ unicode_display = unicode_default;
1198+ else if (streq (optarg, "locale") || streq (optarg, "l"))
1199+ unicode_display = unicode_locale;
1200+ else if (streq (optarg, "escape") || streq (optarg, "e"))
1201+ unicode_display = unicode_escape;
1202+ else if (streq (optarg, "invalid") || streq (optarg, "i"))
1203+ unicode_display = unicode_invalid;
1204+ else if (streq (optarg, "hex") || streq (optarg, "x"))
1205+ unicode_display = unicode_hex;
1206+ else if (streq (optarg, "highlight") || streq (optarg, "h"))
1207+ unicode_display = unicode_highlight;
1208+ else
1209+ fatal (_("invalid argument to -U/--unicode: %s"), optarg);
1210+ break;
1211
1212 case 'V':
1213 case 'v':
1214@@ -260,6 +307,9 @@ main (int argc, char **argv)
1215 }
1216 }
1217
1218+ if (unicode_display != unicode_default)
1219+ encoding = 'S';
1220+
1221 if (numeric_opt != 0)
1222 {
1223 string_min = (int) strtoul (argv[numeric_opt - 1] + 1, &s, 0);
1224@@ -295,14 +345,14 @@ main (int argc, char **argv)
1225 {
1226 datasection_only = FALSE;
1227 SET_BINARY (fileno (stdin));
1228- print_strings ("{standard input}", stdin, 0, 0, 0, (char *) NULL);
1229+ print_strings ("{standard input}", stdin, 0, 0, (char *) NULL);
1230 files_given = TRUE;
1231 }
1232 else
1233 {
1234 for (; optind < argc; ++optind)
1235 {
1236- if (strcmp (argv[optind], "-") == 0)
1237+ if (streq (argv[optind], "-"))
1238 datasection_only = FALSE;
1239 else
1240 {
1241@@ -344,7 +394,7 @@ strings_a_section (bfd *abfd, asection *
1242 }
1243
1244 *got_a_section = TRUE;
1245- print_strings (filename, NULL, sect->filepos, 0, sectsize, (char *) mem);
1246+ print_strings (filename, NULL, sect->filepos, sectsize, (char *) mem);
1247 free (mem);
1248 }
1249
1250@@ -429,7 +479,7 @@ strings_file (char *file)
1251 return FALSE;
1252 }
1253
1254- print_strings (file, stream, (file_ptr) 0, 0, 0, (char *) 0);
1255+ print_strings (file, stream, (file_ptr) 0, 0, (char *) NULL);
1256
1257 if (fclose (stream) == EOF)
1258 {
1259@@ -553,11 +603,632 @@ unget_part_char (long c, file_ptr *addre
1260 }
1261 }
1262 }
1263+
1264+
1265+static void
1266+print_filename_and_address (const char * filename, file_ptr address)
1267+{
1268+ if (print_filenames)
1269+ printf ("%s: ", filename);
1270+
1271+ if (! print_addresses)
1272+ return;
1273+
1274+ switch (address_radix)
1275+ {
1276+ case 8:
1277+ if (sizeof (address) > sizeof (long))
1278+ {
1279+#ifndef __MSVCRT__
1280+ printf ("%7llo ", (unsigned long long) address);
1281+#else
1282+ printf ("%7I64o ", (unsigned long long) address);
1283+#endif
1284+ }
1285+ else
1286+ printf ("%7lo ", (unsigned long) address);
1287+ break;
1288+
1289+ case 10:
1290+ if (sizeof (address) > sizeof (long))
1291+ {
1292+#ifndef __MSVCRT__
1293+ printf ("%7llu ", (unsigned long long) address);
1294+#else
1295+ printf ("%7I64d ", (unsigned long long) address);
1296+#endif
1297+ }
1298+ else
1299+ printf ("%7ld ", (long) address);
1300+ break;
1301+
1302+ case 16:
1303+ if (sizeof (address) > sizeof (long))
1304+ {
1305+#ifndef __MSVCRT__
1306+ printf ("%7llx ", (unsigned long long) address);
1307+#else
1308+ printf ("%7I64x ", (unsigned long long) address);
1309+#endif
1310+ }
1311+ else
1312+ printf ("%7lx ", (unsigned long) address);
1313+ break;
1314+ }
1315+}
1316+
1317+/* Return non-zero if the bytes starting at BUFFER form a valid UTF-8 encoding.
1318+ If the encoding is valid then returns the number of bytes it uses. */
1319+
1320+static unsigned int
1321+is_valid_utf8 (const unsigned char * buffer, unsigned long buflen)
1322+{
1323+ if (buffer[0] < 0xc0)
1324+ return 0;
1325+
1326+ if (buflen < 2)
1327+ return 0;
1328+
1329+ if ((buffer[1] & 0xc0) != 0x80)
1330+ return 0;
1331+
1332+ if ((buffer[0] & 0x20) == 0)
1333+ return 2;
1334+
1335+ if (buflen < 3)
1336+ return 0;
1337+
1338+ if ((buffer[2] & 0xc0) != 0x80)
1339+ return 0;
1340+
1341+ if ((buffer[0] & 0x10) == 0)
1342+ return 3;
1343+
1344+ if (buflen < 4)
1345+ return 0;
1346+
1347+ if ((buffer[3] & 0xc0) != 0x80)
1348+ return 0;
1349+
1350+ return 4;
1351+}
1352+
1353+/* Display a UTF-8 encoded character in BUFFER according to the setting
1354+ of unicode_display. The character is known to be valid.
1355+ Returns the number of bytes consumed. */
1356+
1357+static unsigned int
1358+display_utf8_char (const unsigned char * buffer)
1359+{
1360+ unsigned int j;
1361+ unsigned int utf8_len;
1362+
1363+ switch (buffer[0] & 0x30)
1364+ {
1365+ case 0x00:
1366+ case 0x10:
1367+ utf8_len = 2;
1368+ break;
1369+ case 0x20:
1370+ utf8_len = 3;
1371+ break;
1372+ default:
1373+ utf8_len = 4;
1374+ }
1375+
1376+ switch (unicode_display)
1377+ {
1378+ default:
1379+ fprintf (stderr, "ICE: unexpected unicode display type\n");
1380+ break;
1381+
1382+ case unicode_escape:
1383+ case unicode_highlight:
1384+ if (unicode_display == unicode_highlight && isatty (1))
1385+ printf ("\x1B[31;47m"); /* Red. */
1386+
1387+ switch (utf8_len)
1388+ {
1389+ case 2:
1390+ printf ("\\u%02x%02x",
1391+ ((buffer[0] & 0x1c) >> 2),
1392+ ((buffer[0] & 0x03) << 6) | (buffer[1] & 0x3f));
1393+ break;
1394+
1395+ case 3:
1396+ printf ("\\u%02x%02x",
1397+ ((buffer[0] & 0x0f) << 4) | ((buffer[1] & 0x3c) >> 2),
1398+ ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3f)));
1399+ break;
1400+
1401+ case 4:
1402+ printf ("\\u%02x%02x%02x",
1403+ ((buffer[0] & 0x07) << 6) | ((buffer[1] & 0x3c) >> 2),
1404+ ((buffer[1] & 0x03) << 6) | ((buffer[2] & 0x3c) >> 2),
1405+ ((buffer[2] & 0x03) << 6) | ((buffer[3] & 0x3f)));
1406+ break;
1407+ default:
1408+ /* URG. */
1409+ break;
1410+ }
1411+
1412+ if (unicode_display == unicode_highlight && isatty (1))
1413+ printf ("\033[0m"); /* Default colour. */
1414+ break;
1415+
1416+ case unicode_hex:
1417+ putchar ('<');
1418+ printf ("0x");
1419+ for (j = 0; j < utf8_len; j++)
1420+ printf ("%02x", buffer [j]);
1421+ putchar ('>');
1422+ break;
1423+
1424+ case unicode_locale:
1425+ printf ("%.1s", buffer);
1426+ break;
1427+ }
1428+
1429+ return utf8_len;
1430+}
1431+
1432+/* Display strings in BUFFER. Treat any UTF-8 encoded characters encountered
1433+ according to the setting of the unicode_display variable. The buffer
1434+ contains BUFLEN bytes.
1435+
1436+ Display the characters as if they started at ADDRESS and are contained in
1437+ FILENAME. */
1438+
1439+static void
1440+print_unicode_buffer (const char * filename,
1441+ file_ptr address,
1442+ const unsigned char * buffer,
1443+ unsigned long buflen)
1444+{
1445+ /* Paranoia checks... */
1446+ if (filename == NULL
1447+ || buffer == NULL
1448+ || unicode_display == unicode_default
1449+ || encoding != 'S'
1450+ || encoding_bytes != 1)
1451+ {
1452+ fprintf (stderr, "ICE: bad arguments to print_unicode_buffer\n");
1453+ return;
1454+ }
1455+
1456+ if (buflen == 0)
1457+ return;
1458+
1459+ /* We must only display strings that are at least string_min *characters*
1460+ long. So we scan the buffer in two stages. First we locate the start
1461+ of a potential string. Then we walk along it until we have found
1462+ string_min characters. Then we go back to the start point and start
1463+ displaying characters according to the unicode_display setting. */
1464+
1465+ unsigned long start_point = 0;
1466+ unsigned long i = 0;
1467+ unsigned int char_len = 1;
1468+ unsigned int num_found = 0;
1469+
1470+ for (i = 0; i < buflen; i += char_len)
1471+ {
1472+ int c = buffer[i];
1473+
1474+ char_len = 1;
1475+
1476+ /* Find the first potential character of a string. */
1477+ if (! STRING_ISGRAPHIC (c))
1478+ {
1479+ num_found = 0;
1480+ continue;
1481+ }
1482+
1483+ if (c > 126)
1484+ {
1485+ if (c < 0xc0)
1486+ {
1487+ num_found = 0;
1488+ continue;
1489+ }
1490+
1491+ if ((char_len = is_valid_utf8 (buffer + i, buflen - i)) == 0)
1492+ {
1493+ char_len = 1;
1494+ num_found = 0;
1495+ continue;
1496+ }
1497+
1498+ if (unicode_display == unicode_invalid)
1499+ {
1500+ /* We have found a valid UTF-8 character, but we treat it as non-graphic. */
1501+ num_found = 0;
1502+ continue;
1503+ }
1504+ }
1505+
1506+ if (num_found == 0)
1507+ /* We have found a potential starting point for a string. */
1508+ start_point = i;
1509+
1510+ ++ num_found;
1511+
1512+ if (num_found >= string_min)
1513+ break;
1514+ }
1515+
1516+ if (num_found < string_min)
1517+ return;
1518+
1519+ print_filename_and_address (filename, address + start_point);
1520+
1521+ /* We have found string_min characters. Display them and any
1522+ more that follow. */
1523+ for (i = start_point; i < buflen; i += char_len)
1524+ {
1525+ int c = buffer[i];
1526+
1527+ char_len = 1;
1528+
1529+ if (! STRING_ISGRAPHIC (c))
1530+ break;
1531+ else if (c < 127)
1532+ putchar (c);
1533+ else if (! is_valid_utf8 (buffer + i, buflen - i))
1534+ break;
1535+ else if (unicode_display == unicode_invalid)
1536+ break;
1537+ else
1538+ char_len = display_utf8_char (buffer + i);
1539+ }
1540+
1541+ if (output_separator)
1542+ fputs (output_separator, stdout);
1543+ else
1544+ putchar ('\n');
1545+
1546+ /* FIXME: Using tail recursion here is lazy programming... */
1547+ print_unicode_buffer (filename, address + i, buffer + i, buflen - i);
1548+}
1549+
1550+static int
1551+get_unicode_byte (FILE * stream,
1552+ unsigned char * putback,
1553+ unsigned int * num_putback,
1554+ unsigned int * num_read)
1555+{
1556+ if (* num_putback > 0)
1557+ {
1558+ * num_putback = * num_putback - 1;
1559+ return putback [* num_putback];
1560+ }
1561+
1562+ * num_read = * num_read + 1;
1563+
1564+#if defined(HAVE_GETC_UNLOCKED) && HAVE_DECL_GETC_UNLOCKED
1565+ return getc_unlocked (stream);
1566+#else
1567+ return getc (stream);
1568+#endif
1569+}
1570+
1571+/* Helper function for print_unicode_stream. */
1572+
1573+static void
1574+print_unicode_stream_body (const char * filename,
1575+ file_ptr address,
1576+ FILE * stream,
1577+ unsigned char * putback_buf,
1578+ unsigned int num_putback,
1579+ unsigned char * print_buf)
1580+{
1581+ /* It would be nice if we could just read the stream into a buffer
1582+ and then process if with print_unicode_buffer. But the input
1583+ might be huge or it might time-locked (eg stdin). So instead
1584+ we go one byte at a time... */
1585+
1586+ file_ptr start_point = 0;
1587+ unsigned int num_read = 0;
1588+ unsigned int num_chars = 0;
1589+ unsigned int num_print = 0;
1590+ int c;
1591+
1592+ /* Find a series of string_min characters. Put them into print_buf. */
1593+ do
1594+ {
1595+ if (num_chars >= string_min)
1596+ break;
1597+
1598+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1599+ if (c == EOF)
1600+ break;
1601+
1602+ if (! STRING_ISGRAPHIC (c))
1603+ {
1604+ num_chars = num_print = 0;
1605+ continue;
1606+ }
1607+
1608+ if (num_chars == 0)
1609+ start_point = num_read - 1;
1610+
1611+ if (c < 127)
1612+ {
1613+ print_buf[num_print] = c;
1614+ num_chars ++;
1615+ num_print ++;
1616+ continue;
1617+ }
1618+
1619+ if (c < 0xc0)
1620+ {
1621+ num_chars = num_print = 0;
1622+ continue;
1623+ }
1624+
1625+ /* We *might* have a UTF-8 sequence. Time to start peeking. */
1626+ char utf8[4];
1627+
1628+ utf8[0] = c;
1629+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1630+ if (c == EOF)
1631+ break;
1632+ utf8[1] = c;
1633+
1634+ if ((utf8[1] & 0xc0) != 0x80)
1635+ {
1636+ /* Invalid UTF-8. */
1637+ putback_buf[num_putback++] = utf8[1];
1638+ num_chars = num_print = 0;
1639+ continue;
1640+ }
1641+ else if ((utf8[0] & 0x20) == 0)
1642+ {
1643+ /* A valid 2-byte UTF-8 encoding. */
1644+ if (unicode_display == unicode_invalid)
1645+ {
1646+ putback_buf[num_putback++] = utf8[1];
1647+ num_chars = num_print = 0;
1648+ }
1649+ else
1650+ {
1651+ print_buf[num_print ++] = utf8[0];
1652+ print_buf[num_print ++] = utf8[1];
1653+ num_chars ++;
1654+ }
1655+ continue;
1656+ }
1657+
1658+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1659+ if (c == EOF)
1660+ break;
1661+ utf8[2] = c;
1662+
1663+ if ((utf8[2] & 0xc0) != 0x80)
1664+ {
1665+ /* Invalid UTF-8. */
1666+ putback_buf[num_putback++] = utf8[2];
1667+ putback_buf[num_putback++] = utf8[1];
1668+ num_chars = num_print = 0;
1669+ continue;
1670+ }
1671+ else if ((utf8[0] & 0x10) == 0)
1672+ {
1673+ /* A valid 3-byte UTF-8 encoding. */
1674+ if (unicode_display == unicode_invalid)
1675+ {
1676+ putback_buf[num_putback++] = utf8[2];
1677+ putback_buf[num_putback++] = utf8[1];
1678+ num_chars = num_print = 0;
1679+ }
1680+ else
1681+ {
1682+ print_buf[num_print ++] = utf8[0];
1683+ print_buf[num_print ++] = utf8[1];
1684+ print_buf[num_print ++] = utf8[2];
1685+ num_chars ++;
1686+ }
1687+ continue;
1688+ }
1689+
1690+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1691+ if (c == EOF)
1692+ break;
1693+ utf8[3] = c;
1694+
1695+ if ((utf8[3] & 0xc0) != 0x80)
1696+ {
1697+ /* Invalid UTF-8. */
1698+ putback_buf[num_putback++] = utf8[3];
1699+ putback_buf[num_putback++] = utf8[2];
1700+ putback_buf[num_putback++] = utf8[1];
1701+ num_chars = num_print = 0;
1702+ }
1703+ /* We have a valid 4-byte UTF-8 encoding. */
1704+ else if (unicode_display == unicode_invalid)
1705+ {
1706+ putback_buf[num_putback++] = utf8[3];
1707+ putback_buf[num_putback++] = utf8[1];
1708+ putback_buf[num_putback++] = utf8[2];
1709+ num_chars = num_print = 0;
1710+ }
1711+ else
1712+ {
1713+ print_buf[num_print ++] = utf8[0];
1714+ print_buf[num_print ++] = utf8[1];
1715+ print_buf[num_print ++] = utf8[2];
1716+ print_buf[num_print ++] = utf8[3];
1717+ num_chars ++;
1718+ }
1719+ }
1720+ while (1);
1721+
1722+ if (num_chars >= string_min)
1723+ {
1724+ /* We know that we have string_min valid characters in print_buf,
1725+ and there may be more to come in the stream. Start displaying
1726+ them. */
1727+
1728+ print_filename_and_address (filename, address + start_point);
1729+
1730+ unsigned int i;
1731+ for (i = 0; i < num_print;)
1732+ {
1733+ if (print_buf[i] < 127)
1734+ putchar (print_buf[i++]);
1735+ else
1736+ i += display_utf8_char (print_buf + i);
1737+ }
1738+
1739+ /* OK so now we have to start read unchecked bytes. */
1740+
1741+ /* Find a series of string_min characters. Put them into print_buf. */
1742+ do
1743+ {
1744+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1745+ if (c == EOF)
1746+ break;
1747+
1748+ if (! STRING_ISGRAPHIC (c))
1749+ break;
1750+
1751+ if (c < 127)
1752+ {
1753+ putchar (c);
1754+ continue;
1755+ }
1756+
1757+ if (c < 0xc0)
1758+ break;
1759+
1760+ /* We *might* have a UTF-8 sequence. Time to start peeking. */
1761+ unsigned char utf8[4];
1762+
1763+ utf8[0] = c;
1764+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1765+ if (c == EOF)
1766+ break;
1767+ utf8[1] = c;
1768+
1769+ if ((utf8[1] & 0xc0) != 0x80)
1770+ {
1771+ /* Invalid UTF-8. */
1772+ putback_buf[num_putback++] = utf8[1];
1773+ break;
1774+ }
1775+ else if ((utf8[0] & 0x20) == 0)
1776+ {
1777+ /* Valid 2-byte UTF-8. */
1778+ if (unicode_display == unicode_invalid)
1779+ {
1780+ putback_buf[num_putback++] = utf8[1];
1781+ break;
1782+ }
1783+ else
1784+ {
1785+ (void) display_utf8_char (utf8);
1786+ continue;
1787+ }
1788+ }
1789+
1790+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1791+ if (c == EOF)
1792+ break;
1793+ utf8[2] = c;
1794+
1795+ if ((utf8[2] & 0xc0) != 0x80)
1796+ {
1797+ /* Invalid UTF-8. */
1798+ putback_buf[num_putback++] = utf8[2];
1799+ putback_buf[num_putback++] = utf8[1];
1800+ break;
1801+ }
1802+ else if ((utf8[0] & 0x10) == 0)
1803+ {
1804+ /* Valid 3-byte UTF-8. */
1805+ if (unicode_display == unicode_invalid)
1806+ {
1807+ putback_buf[num_putback++] = utf8[2];
1808+ putback_buf[num_putback++] = utf8[1];
1809+ break;
1810+ }
1811+ else
1812+ {
1813+ (void) display_utf8_char (utf8);
1814+ continue;
1815+ }
1816+ }
1817+
1818+ c = get_unicode_byte (stream, putback_buf, & num_putback, & num_read);
1819+ if (c == EOF)
1820+ break;
1821+ utf8[3] = c;
1822+
1823+ if ((utf8[3] & 0xc0) != 0x80)
1824+ {
1825+ /* Invalid UTF-8. */
1826+ putback_buf[num_putback++] = utf8[3];
1827+ putback_buf[num_putback++] = utf8[2];
1828+ putback_buf[num_putback++] = utf8[1];
1829+ break;
1830+ }
1831+ else if (unicode_display == unicode_invalid)
1832+ {
1833+ putback_buf[num_putback++] = utf8[3];
1834+ putback_buf[num_putback++] = utf8[2];
1835+ putback_buf[num_putback++] = utf8[1];
1836+ break;
1837+ }
1838+ else
1839+ /* A valid 4-byte UTF-8 encoding. */
1840+ (void) display_utf8_char (utf8);
1841+ }
1842+ while (1);
1843+
1844+ if (output_separator)
1845+ fputs (output_separator, stdout);
1846+ else
1847+ putchar ('\n');
1848+ }
1849+
1850+ if (c != EOF)
1851+ /* FIXME: Using tail recursion here is lazy, but it works. */
1852+ print_unicode_stream_body (filename, address + num_read, stream, putback_buf, num_putback, print_buf);
1853+}
1854+
1855+/* Display strings read in from STREAM. Treat any UTF-8 encoded characters
1856+ encountered according to the setting of the unicode_display variable.
1857+ The stream is positioned at ADDRESS and is attached to FILENAME. */
1858+
1859+static void
1860+print_unicode_stream (const char * filename,
1861+ file_ptr address,
1862+ FILE * stream)
1863+{
1864+ /* Paranoia checks... */
1865+ if (filename == NULL
1866+ || stream == NULL
1867+ || unicode_display == unicode_default
1868+ || encoding != 'S'
1869+ || encoding_bytes != 1)
1870+ {
1871+ fprintf (stderr, "ICE: bad arguments to print_unicode_stream\n");
1872+ return;
1873+ }
1874+
1875+ /* Allocate space for string_min 4-byte utf-8 characters. */
1876+ unsigned char * print_buf = xmalloc ((4 * string_min) + 1);
1877+ /* We should never have to put back more than 4 bytes. */
1878+ unsigned char putback_buf[5];
1879+ unsigned int num_putback = 0;
1880+
1881+ print_unicode_stream_body (filename, address, stream, putback_buf, num_putback, print_buf);
1882+ free (print_buf);
1883+}
1884+
1885
1886 /* Find the strings in file FILENAME, read from STREAM.
1887 Assume that STREAM is positioned so that the next byte read
1888 is at address ADDRESS in the file.
1889- Stop reading at address STOP_POINT in the file, if nonzero.
1890
1891 If STREAM is NULL, do not read from it.
1892 The caller can supply a buffer of characters
1893@@ -568,20 +1239,29 @@ unget_part_char (long c, file_ptr *addre
1894
1895 static void
1896 print_strings (const char *filename, FILE *stream, file_ptr address,
1897- int stop_point, int magiccount, char *magic)
1898+ int magiccount, char *magic)
1899 {
1900+ if (unicode_display != unicode_default)
1901+ {
1902+ if (magic != NULL)
1903+ print_unicode_buffer (filename, address,
1904+ (const unsigned char *) magic, magiccount);
1905+
1906+ if (stream != NULL)
1907+ print_unicode_stream (filename, address, stream);
1908+ return;
1909+ }
1910+
1911 char *buf = (char *) xmalloc (sizeof (char) * (string_min + 1));
1912
1913 while (1)
1914 {
1915 file_ptr start;
1916- int i;
1917+ unsigned int i;
1918 long c;
1919
1920 /* See if the next `string_min' chars are all graphic chars. */
1921 tryline:
1922- if (stop_point && address >= stop_point)
1923- break;
1924 start = address;
1925 for (i = 0; i < string_min; i++)
1926 {
1927@@ -604,69 +1284,7 @@ print_strings (const char *filename, FIL
1928 /* We found a run of `string_min' graphic characters. Print up
1929 to the next non-graphic character. */
1930
1931- if (print_filenames)
1932- printf ("%s: ", filename);
1933- if (print_addresses)
1934- switch (address_radix)
1935- {
1936- case 8:
1937-#ifdef HAVE_LONG_LONG
1938- if (sizeof (start) > sizeof (long))
1939- {
1940-# ifndef __MSVCRT__
1941- printf ("%7llo ", (unsigned long long) start);
1942-# else
1943- printf ("%7I64o ", (unsigned long long) start);
1944-# endif
1945- }
1946- else
1947-#elif !BFD_HOST_64BIT_LONG
1948- if (start != (unsigned long) start)
1949- printf ("++%7lo ", (unsigned long) start);
1950- else
1951-#endif
1952- printf ("%7lo ", (unsigned long) start);
1953- break;
1954-
1955- case 10:
1956-#ifdef HAVE_LONG_LONG
1957- if (sizeof (start) > sizeof (long))
1958- {
1959-# ifndef __MSVCRT__
1960- printf ("%7llu ", (unsigned long long) start);
1961-# else
1962- printf ("%7I64d ", (unsigned long long) start);
1963-# endif
1964- }
1965- else
1966-#elif !BFD_HOST_64BIT_LONG
1967- if (start != (unsigned long) start)
1968- printf ("++%7lu ", (unsigned long) start);
1969- else
1970-#endif
1971- printf ("%7ld ", (long) start);
1972- break;
1973-
1974- case 16:
1975-#ifdef HAVE_LONG_LONG
1976- if (sizeof (start) > sizeof (long))
1977- {
1978-# ifndef __MSVCRT__
1979- printf ("%7llx ", (unsigned long long) start);
1980-# else
1981- printf ("%7I64x ", (unsigned long long) start);
1982-# endif
1983- }
1984- else
1985-#elif !BFD_HOST_64BIT_LONG
1986- if (start != (unsigned long) start)
1987- printf ("%lx%8.8lx ", (unsigned long) (start >> 32),
1988- (unsigned long) (start & 0xffffffff));
1989- else
1990-#endif
1991- printf ("%7lx ", (unsigned long) start);
1992- break;
1993- }
1994+ print_filename_and_address (filename, start);
1995
1996 buf[i] = '\0';
1997 fputs (buf, stdout);
1998@@ -718,6 +1336,8 @@ usage (FILE *stream, int status)
1999 -T --target=<BFDNAME> Specify the binary file format\n\
2000 -e --encoding={s,S,b,l,B,L} Select character size and endianness:\n\
2001 s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit\n\
2002+ --unicode={default|show|invalid|hex|escape|highlight}\n\
2003+ -u {d|s|i|x|e|h} Specify how to treat UTF-8 encoded unicode characters\n\
2004 -s --output-separator=<string> String used to separate strings in output.\n\
2005 @<file> Read options from <file>\n\
2006 -h --help Display this information\n\
diff --git a/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-45078.patch b/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-45078.patch
new file mode 100644
index 0000000000..f118e2599b
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/0001-CVE-2021-45078.patch
@@ -0,0 +1,255 @@
1From 161e87d12167b1e36193385485c1f6ce92f74f02 Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Wed, 15 Dec 2021 11:48:42 +1030
4Subject: [PATCH] PR28694, Out-of-bounds write in stab_xcoff_builtin_type
5
6 PR 28694
7 * stabs.c (stab_xcoff_builtin_type): Make typenum unsigned.
8 Negate typenum earlier, simplifying bounds checking. Correct
9 off-by-one indexing. Adjust switch cases.
10
11
12CVE: CVE-2021-45078
13Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=161e87d12167b1e36193385485c1f6ce92f74f02]
14
15Signed-off-by: Sundeep KOKKONDA <sundeep.kokkonda@gmail.com>
16---
17 binutils/stabs.c | 87 ++++++++++++++++++++++++------------------------
18 1 file changed, 43 insertions(+), 44 deletions(-)
19
20
21diff --git a/binutils/stabs.c b/binutils/stabs.c
22index 274bfb0e7fa..83ee3ea5fa4 100644
23--- a/binutils/stabs.c
24+++ b/binutils/stabs.c
25@@ -202,7 +202,7 @@ static debug_type stab_find_type (void *, struct stab_handle *, const int *);
26 static bfd_boolean stab_record_type
27 (void *, struct stab_handle *, const int *, debug_type);
28 static debug_type stab_xcoff_builtin_type
29- (void *, struct stab_handle *, int);
30+ (void *, struct stab_handle *, unsigned int);
31 static debug_type stab_find_tagged_type
32 (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
33 static debug_type *stab_demangle_argtypes
34@@ -3496,166 +3496,167 @@ stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info,
35
36 static debug_type
37 stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
38- int typenum)
39+ unsigned int typenum)
40 {
41 debug_type rettype;
42 const char *name;
43
44- if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
45+ typenum = -typenum - 1;
46+ if (typenum >= XCOFF_TYPE_COUNT)
47 {
48- fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum);
49+ fprintf (stderr, _("Unrecognized XCOFF type %d\n"), -typenum - 1);
50 return DEBUG_TYPE_NULL;
51 }
52- if (info->xcoff_types[-typenum] != NULL)
53- return info->xcoff_types[-typenum];
54+ if (info->xcoff_types[typenum] != NULL)
55+ return info->xcoff_types[typenum];
56
57- switch (-typenum)
58+ switch (typenum)
59 {
60- case 1:
61+ case 0:
62 /* The size of this and all the other types are fixed, defined
63 by the debugging format. */
64 name = "int";
65 rettype = debug_make_int_type (dhandle, 4, FALSE);
66 break;
67- case 2:
68+ case 1:
69 name = "char";
70 rettype = debug_make_int_type (dhandle, 1, FALSE);
71 break;
72- case 3:
73+ case 2:
74 name = "short";
75 rettype = debug_make_int_type (dhandle, 2, FALSE);
76 break;
77- case 4:
78+ case 3:
79 name = "long";
80 rettype = debug_make_int_type (dhandle, 4, FALSE);
81 break;
82- case 5:
83+ case 4:
84 name = "unsigned char";
85 rettype = debug_make_int_type (dhandle, 1, TRUE);
86 break;
87- case 6:
88+ case 5:
89 name = "signed char";
90 rettype = debug_make_int_type (dhandle, 1, FALSE);
91 break;
92- case 7:
93+ case 6:
94 name = "unsigned short";
95 rettype = debug_make_int_type (dhandle, 2, TRUE);
96 break;
97- case 8:
98+ case 7:
99 name = "unsigned int";
100 rettype = debug_make_int_type (dhandle, 4, TRUE);
101 break;
102- case 9:
103+ case 8:
104 name = "unsigned";
105 rettype = debug_make_int_type (dhandle, 4, TRUE);
106 break;
107- case 10:
108+ case 9:
109 name = "unsigned long";
110 rettype = debug_make_int_type (dhandle, 4, TRUE);
111 break;
112- case 11:
113+ case 10:
114 name = "void";
115 rettype = debug_make_void_type (dhandle);
116 break;
117- case 12:
118+ case 11:
119 /* IEEE single precision (32 bit). */
120 name = "float";
121 rettype = debug_make_float_type (dhandle, 4);
122 break;
123- case 13:
124+ case 12:
125 /* IEEE double precision (64 bit). */
126 name = "double";
127 rettype = debug_make_float_type (dhandle, 8);
128 break;
129- case 14:
130+ case 13:
131 /* This is an IEEE double on the RS/6000, and different machines
132 with different sizes for "long double" should use different
133 negative type numbers. See stabs.texinfo. */
134 name = "long double";
135 rettype = debug_make_float_type (dhandle, 8);
136 break;
137- case 15:
138+ case 14:
139 name = "integer";
140 rettype = debug_make_int_type (dhandle, 4, FALSE);
141 break;
142- case 16:
143+ case 15:
144 name = "boolean";
145 rettype = debug_make_bool_type (dhandle, 4);
146 break;
147- case 17:
148+ case 16:
149 name = "short real";
150 rettype = debug_make_float_type (dhandle, 4);
151 break;
152- case 18:
153+ case 17:
154 name = "real";
155 rettype = debug_make_float_type (dhandle, 8);
156 break;
157- case 19:
158+ case 18:
159 /* FIXME */
160 name = "stringptr";
161 rettype = NULL;
162 break;
163- case 20:
164+ case 19:
165 /* FIXME */
166 name = "character";
167 rettype = debug_make_int_type (dhandle, 1, TRUE);
168 break;
169- case 21:
170+ case 20:
171 name = "logical*1";
172 rettype = debug_make_bool_type (dhandle, 1);
173 break;
174- case 22:
175+ case 21:
176 name = "logical*2";
177 rettype = debug_make_bool_type (dhandle, 2);
178 break;
179- case 23:
180+ case 22:
181 name = "logical*4";
182 rettype = debug_make_bool_type (dhandle, 4);
183 break;
184- case 24:
185+ case 23:
186 name = "logical";
187 rettype = debug_make_bool_type (dhandle, 4);
188 break;
189- case 25:
190+ case 24:
191 /* Complex type consisting of two IEEE single precision values. */
192 name = "complex";
193 rettype = debug_make_complex_type (dhandle, 8);
194 break;
195- case 26:
196+ case 25:
197 /* Complex type consisting of two IEEE double precision values. */
198 name = "double complex";
199 rettype = debug_make_complex_type (dhandle, 16);
200 break;
201- case 27:
202+ case 26:
203 name = "integer*1";
204 rettype = debug_make_int_type (dhandle, 1, FALSE);
205 break;
206- case 28:
207+ case 27:
208 name = "integer*2";
209 rettype = debug_make_int_type (dhandle, 2, FALSE);
210 break;
211- case 29:
212+ case 28:
213 name = "integer*4";
214 rettype = debug_make_int_type (dhandle, 4, FALSE);
215 break;
216- case 30:
217+ case 29:
218 /* FIXME */
219 name = "wchar";
220 rettype = debug_make_int_type (dhandle, 2, FALSE);
221 break;
222- case 31:
223+ case 30:
224 name = "long long";
225 rettype = debug_make_int_type (dhandle, 8, FALSE);
226 break;
227- case 32:
228+ case 31:
229 name = "unsigned long long";
230 rettype = debug_make_int_type (dhandle, 8, TRUE);
231 break;
232- case 33:
233+ case 32:
234 name = "logical*8";
235 rettype = debug_make_bool_type (dhandle, 8);
236 break;
237- case 34:
238+ case 33:
239 name = "integer*8";
240 rettype = debug_make_int_type (dhandle, 8, FALSE);
241 break;
242@@ -3664,9 +3665,7 @@ stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
243 }
244
245 rettype = debug_name_type (dhandle, name, rettype);
246-
247- info->xcoff_types[-typenum] = rettype;
248-
249+ info->xcoff_types[typenum] = rettype;
250 return rettype;
251 }
252
253--
2542.27.0
255
diff --git a/meta/recipes-devtools/binutils/binutils/0002-CVE-2021-20197.patch b/meta/recipes-devtools/binutils/binutils/0002-CVE-2021-20197.patch
deleted file mode 100644
index 3771f571eb..0000000000
--- a/meta/recipes-devtools/binutils/binutils/0002-CVE-2021-20197.patch
+++ /dev/null
@@ -1,170 +0,0 @@
1From d3edaa91d4cf7202ec14342410194841e2f67f12 Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Fri, 26 Feb 2021 11:30:32 +1030
4Subject: [PATCH] Reinstate various pieces backed out from smart_rename changes
5
6In the interests of a stable release various last minute smart_rename
7patches were backed out of the 2.36 branch. The main reason to
8reinstate some of those backed out changes here is to make necessary
9followup fixes to commit 8e03235147a9 simple cherry-picks from
10mainline. A secondary reason is that ar -M support isn't fixed for
11pr26945 without this patch.
12
13 PR 26945
14 * ar.c: Don't include libbfd.h.
15 (write_archive): Replace xmalloc+strcpy with xstrdup.
16 * arsup.c (temp_name, real_ofd): New static variables.
17 (ar_open): Use make_tempname and bfd_fdopenw.
18 (ar_save): Adjust to suit ar_open changes.
19 * objcopy.c: Don't include libbfd.h.
20 * rename.c: Rename and reorder variables.
21
22(cherry picked from commit 95b91a043aeaeb546d2fea556d84a2de1e917770)
23
24Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d3edaa91d4cf7202ec14342410194841e2f67f12]
25CVE: CVE-2021-20197
26Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
27---
28 binutils/ar.c | 4 +---
29 binutils/arsup.c | 37 +++++++++++++++++++++++++------------
30 binutils/objcopy.c | 1 -
31 binutils/rename.c | 6 +++---
32 5 files changed, 42 insertions(+), 19 deletions(-)
33
34diff --git a/binutils/ar.c b/binutils/ar.c
35index 3a91708b51c..44df48c5c67 100644
36--- a/binutils/ar.c
37+++ b/binutils/ar.c
38@@ -25,7 +25,6 @@
39
40 #include "sysdep.h"
41 #include "bfd.h"
42-#include "libbfd.h"
43 #include "libiberty.h"
44 #include "progress.h"
45 #include "getopt.h"
46@@ -1255,8 +1254,7 @@ write_archive (bfd *iarch)
47 bfd *contents_head = iarch->archive_next;
48 int ofd = -1;
49
50- old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
51- strcpy (old_name, bfd_get_filename (iarch));
52+ old_name = xstrdup (bfd_get_filename (iarch));
53 new_name = make_tempname (old_name, &ofd);
54
55 if (new_name == NULL)
56diff --git a/binutils/arsup.c b/binutils/arsup.c
57index 0a1f63f6456..f7ce8f0bc82 100644
58--- a/binutils/arsup.c
59+++ b/binutils/arsup.c
60@@ -42,6 +42,8 @@ extern int deterministic;
61
62 static bfd *obfd;
63 static char *real_name;
64+static char *temp_name;
65+static int real_ofd;
66 static FILE *outfile;
67
68 static void
69@@ -149,27 +151,24 @@ maybequit (void)
70 void
71 ar_open (char *name, int t)
72 {
73- char *tname;
74- const char *bname = lbasename (name);
75- real_name = name;
76+ real_name = xstrdup (name);
77+ temp_name = make_tempname (real_name, &real_ofd);
78
79- /* Prepend tmp- to the beginning, to avoid file-name clashes after
80- truncation on filesystems with limited namespaces (DOS). */
81- if (asprintf (&tname, "%.*stmp-%s", (int) (bname - name), name, bname) == -1)
82+ if (temp_name == NULL)
83 {
84- fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"),
85+ fprintf (stderr, _("%s: Can't open temporary file (%s)\n"),
86 program_name, strerror(errno));
87 maybequit ();
88 return;
89 }
90
91- obfd = bfd_openw (tname, NULL);
92+ obfd = bfd_fdopenw (temp_name, NULL, real_ofd);
93
94 if (!obfd)
95 {
96 fprintf (stderr,
97 _("%s: Can't open output archive %s\n"),
98- program_name, tname);
99+ program_name, temp_name);
100
101 maybequit ();
102 }
103@@ -344,16 +343,30 @@ ar_save (void)
104 }
105 else
106 {
107- char *ofilename = xstrdup (bfd_get_filename (obfd));
108+ struct stat target_stat;
109
110 if (deterministic > 0)
111 obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
112
113 bfd_close (obfd);
114
115- smart_rename (ofilename, real_name, NULL);
116+ if (stat (real_name, &target_stat) != 0)
117+ {
118+ /* The temp file created in ar_open has mode 0600 as per mkstemp.
119+ Create the real empty output file here so smart_rename will
120+ update the mode according to the process umask. */
121+ obfd = bfd_openw (real_name, NULL);
122+ if (obfd != NULL)
123+ {
124+ bfd_set_format (obfd, bfd_archive);
125+ bfd_close (obfd);
126+ }
127+ }
128+
129+ smart_rename (temp_name, real_name, NULL);
130 obfd = 0;
131- free (ofilename);
132+ free (temp_name);
133+ free (real_name);
134 }
135 }
136
137diff --git a/binutils/objcopy.c b/binutils/objcopy.c
138index 07a872b5a80..73aa8bc2514 100644
139--- a/binutils/objcopy.c
140+++ b/binutils/objcopy.c
141@@ -20,7 +20,6 @@
142
143 #include "sysdep.h"
144 #include "bfd.h"
145-#include "libbfd.h"
146 #include "progress.h"
147 #include "getopt.h"
148 #include "libiberty.h"
149diff --git a/binutils/rename.c b/binutils/rename.c
150index f471b45fd3f..2ff092ee22b 100644
151--- a/binutils/rename.c
152+++ b/binutils/rename.c
153@@ -130,11 +130,11 @@ int
154 smart_rename (const char *from, const char *to,
155 struct stat *target_stat ATTRIBUTE_UNUSED)
156 {
157- bfd_boolean exists;
158- struct stat s;
159 int ret = 0;
160+ struct stat to_stat;
161+ bfd_boolean exists;
162
163- exists = lstat (to, &s) == 0;
164+ exists = lstat (to, &to_stat) == 0;
165
166 #if defined (_WIN32) && !defined (__CYGWIN32__)
167 /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
168--
1692.31.1
170
diff --git a/meta/recipes-devtools/binutils/binutils/0003-CVE-2021-20197.patch b/meta/recipes-devtools/binutils/binutils/0003-CVE-2021-20197.patch
deleted file mode 100644
index 082b28b29c..0000000000
--- a/meta/recipes-devtools/binutils/binutils/0003-CVE-2021-20197.patch
+++ /dev/null
@@ -1,171 +0,0 @@
1From 8b69e61d4be276bb862698aaafddc3e779d23c8f Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Tue, 23 Feb 2021 09:37:39 +1030
4Subject: [PATCH] PR27456, lstat in rename.c on MinGW
5
6 PR 27456
7 * rename.c: Tidy throughout.
8 (smart_rename): Always copy. Remove windows specific code.
9
10(cherry picked from commit cca8873dd5a6015d5557ea44bc1ea9c252435a29)
11
12Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8b69e61d4be276bb862698aaafddc3e779d23c8f]
13CVE: CVE-2021-20197
14Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
15---
16 binutils/rename.c | 111 ++++++++++++++-------------------------------
17 2 files changed, 40 insertions(+), 76 deletions(-)
18
19diff --git a/binutils/rename.c b/binutils/rename.c
20index 2ff092ee22b..72a9323d72c 100644
21--- a/binutils/rename.c
22+++ b/binutils/rename.c
23@@ -24,14 +24,9 @@
24
25 #ifdef HAVE_GOOD_UTIME_H
26 #include <utime.h>
27-#else /* ! HAVE_GOOD_UTIME_H */
28-#ifdef HAVE_UTIMES
29+#elif defined HAVE_UTIMES
30 #include <sys/time.h>
31-#endif /* HAVE_UTIMES */
32-#endif /* ! HAVE_GOOD_UTIME_H */
33-
34-#if ! defined (_WIN32) || defined (__CYGWIN32__)
35-static int simple_copy (const char *, const char *);
36+#endif
37
38 /* The number of bytes to copy at once. */
39 #define COPY_BUF 8192
40@@ -82,7 +77,6 @@ simple_copy (const char *from, const char *to)
41 }
42 return 0;
43 }
44-#endif /* __CYGWIN32__ or not _WIN32 */
45
46 /* Set the times of the file DESTINATION to be the same as those in
47 STATBUF. */
48@@ -91,87 +85,52 @@ void
49 set_times (const char *destination, const struct stat *statbuf)
50 {
51 int result;
52-
53- {
54 #ifdef HAVE_GOOD_UTIME_H
55- struct utimbuf tb;
56-
57- tb.actime = statbuf->st_atime;
58- tb.modtime = statbuf->st_mtime;
59- result = utime (destination, &tb);
60-#else /* ! HAVE_GOOD_UTIME_H */
61-#ifndef HAVE_UTIMES
62- long tb[2];
63-
64- tb[0] = statbuf->st_atime;
65- tb[1] = statbuf->st_mtime;
66- result = utime (destination, tb);
67-#else /* HAVE_UTIMES */
68- struct timeval tv[2];
69-
70- tv[0].tv_sec = statbuf->st_atime;
71- tv[0].tv_usec = 0;
72- tv[1].tv_sec = statbuf->st_mtime;
73- tv[1].tv_usec = 0;
74- result = utimes (destination, tv);
75-#endif /* HAVE_UTIMES */
76-#endif /* ! HAVE_GOOD_UTIME_H */
77- }
78+ struct utimbuf tb;
79+
80+ tb.actime = statbuf->st_atime;
81+ tb.modtime = statbuf->st_mtime;
82+ result = utime (destination, &tb);
83+#elif defined HAVE_UTIMES
84+ struct timeval tv[2];
85+
86+ tv[0].tv_sec = statbuf->st_atime;
87+ tv[0].tv_usec = 0;
88+ tv[1].tv_sec = statbuf->st_mtime;
89+ tv[1].tv_usec = 0;
90+ result = utimes (destination, tv);
91+#else
92+ long tb[2];
93+
94+ tb[0] = statbuf->st_atime;
95+ tb[1] = statbuf->st_mtime;
96+ result = utime (destination, tb);
97+#endif
98
99 if (result != 0)
100 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
101 }
102
103-/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status
104- that, if non-NULL, is used to fix up timestamps after rename. Return 0 if
105- ok, -1 if error. */
106+/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL,
107+ is used to fix up timestamps. Return 0 if ok, -1 if error.
108+ At one time this function renamed files, but file permissions are
109+ tricky to update given the number of different schemes used by
110+ various systems. So now we just copy. */
111
112 int
113 smart_rename (const char *from, const char *to,
114- struct stat *target_stat ATTRIBUTE_UNUSED)
115+ struct stat *target_stat)
116 {
117- int ret = 0;
118- struct stat to_stat;
119- bfd_boolean exists;
120-
121- exists = lstat (to, &to_stat) == 0;
122-
123-#if defined (_WIN32) && !defined (__CYGWIN32__)
124- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
125- fail instead. Also, chown is not present. */
126-
127- if (exists)
128- remove (to);
129+ int ret;
130
131- ret = rename (from, to);
132+ ret = simple_copy (from, to);
133 if (ret != 0)
134- {
135- /* We have to clean up here. */
136- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
137- unlink (from);
138- }
139-#else
140- /* Avoid a full copy and use rename if TO does not exist. */
141- if (!exists)
142- {
143- if ((ret = rename (from, to)) != 0)
144- {
145- /* We have to clean up here. */
146- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
147- unlink (from);
148- }
149- }
150- else
151- {
152- ret = simple_copy (from, to);
153- if (ret != 0)
154- non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno));
155+ non_fatal (_("unable to copy file '%s'; reason: %s"),
156+ to, strerror (errno));
157
158- if (target_stat != NULL)
159- set_times (to, target_stat);
160- unlink (from);
161- }
162-#endif /* _WIN32 && !__CYGWIN32__ */
163+ if (target_stat != NULL)
164+ set_times (to, target_stat);
165+ unlink (from);
166
167 return ret;
168 }
169--
1702.31.1
171
diff --git a/meta/recipes-devtools/ccache/ccache_4.2.bb b/meta/recipes-devtools/ccache/ccache_4.2.1.bb
index b76bf043f0..99bbe0eca2 100644
--- a/meta/recipes-devtools/ccache/ccache_4.2.bb
+++ b/meta/recipes-devtools/ccache/ccache_4.2.1.bb
@@ -7,14 +7,14 @@ HOMEPAGE = "http://ccache.samba.org"
7SECTION = "devel" 7SECTION = "devel"
8 8
9LICENSE = "GPLv3+" 9LICENSE = "GPLv3+"
10LIC_FILES_CHKSUM = "file://LICENSE.adoc;md5=28afb89f649f309e7ac1aab554564637" 10LIC_FILES_CHKSUM = "file://LICENSE.adoc;md5=698a26b57e513d678e1e7727bf56395b"
11 11
12DEPENDS = "zstd" 12DEPENDS = "zstd"
13 13
14SRC_URI = "https://github.com/ccache/ccache/releases/download/v${PV}/${BP}.tar.gz" 14SRC_URI = "https://github.com/ccache/ccache/releases/download/v${PV}/${BP}.tar.gz"
15SRC_URI += "file://0001-CMake-make-build-of-documentation-optional-842.patch" 15SRC_URI += "file://0001-CMake-make-build-of-documentation-optional-842.patch"
16 16
17SRC_URI[sha256sum] = "dbf139ff32031b54cb47f2d7983269f328df14b5a427882f89f7721e5c411b7e" 17SRC_URI[sha256sum] = "320d2b17d2f76393e5d4bb28c8dee5ca783248e9cd23dff0654694d60f8a4b62"
18 18
19UPSTREAM_CHECK_URI = "https://github.com/ccache/ccache/releases/" 19UPSTREAM_CHECK_URI = "https://github.com/ccache/ccache/releases/"
20 20
diff --git a/meta/recipes-devtools/e2fsprogs/e2fsprogs.inc b/meta/recipes-devtools/e2fsprogs/e2fsprogs.inc
index fb02b2006e..1250a9b99c 100644
--- a/meta/recipes-devtools/e2fsprogs/e2fsprogs.inc
+++ b/meta/recipes-devtools/e2fsprogs/e2fsprogs.inc
@@ -19,7 +19,8 @@ LIC_FILES_CHKSUM = "file://NOTICE;md5=d50be0580c0b0a7fbc7a4830bbe6c12b \
19SECTION = "base" 19SECTION = "base"
20DEPENDS = "util-linux attr autoconf-archive" 20DEPENDS = "util-linux attr autoconf-archive"
21 21
22SRC_URI = "git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git;branch=master" 22SRC_URI = "git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git;branch=master \
23 file://0001-e2fsck-fix-last-mount-write-time-when-e2fsck-is-forc.patch"
23S = "${WORKDIR}/git" 24S = "${WORKDIR}/git"
24 25
25inherit autotools gettext texinfo pkgconfig multilib_header update-alternatives ptest 26inherit autotools gettext texinfo pkgconfig multilib_header update-alternatives ptest
diff --git a/meta/recipes-devtools/e2fsprogs/e2fsprogs/0001-e2fsck-fix-last-mount-write-time-when-e2fsck-is-forc.patch b/meta/recipes-devtools/e2fsprogs/e2fsprogs/0001-e2fsck-fix-last-mount-write-time-when-e2fsck-is-forc.patch
new file mode 100644
index 0000000000..d679b25b1d
--- /dev/null
+++ b/meta/recipes-devtools/e2fsprogs/e2fsprogs/0001-e2fsck-fix-last-mount-write-time-when-e2fsck-is-forc.patch
@@ -0,0 +1,66 @@
1From 2c69c94217b6db083d601d4fd62d6ab6c1628fee Mon Sep 17 00:00:00 2001
2From: Lukas Czerner <lczerner@redhat.com>
3Date: Mon, 14 Jun 2021 15:27:25 +0200
4Subject: [PATCH] e2fsck: fix last mount/write time when e2fsck is forced
5
6With commit c52d930f e2fsck is no longer able to fix bad last
7mount/write time by default because it is conditioned on s_checkinterval
8not being zero, which it is by default.
9
10One place where it matters is when other e2fsprogs tools require to run
11full file system check before a certain operation. If the last mount
12time is for any reason in future, it will not allow it to run even if
13full e2fsck is ran.
14
15Fix it by checking the last mount/write time when the e2fsck is forced,
16except for the case where we know the system clock is broken.
17
18[ Reworked the conditionals so error messages claiming that the last
19 write/mount time were corrupted wouldn't be always printed when the
20 e2fsck was run with the -f option, thus causing 299 out of 372
21 regression tests to fail. -- TYT ]
22
23Fixes: c52d930f ("e2fsck: don't check for future superblock times if checkinterval == 0")
24Reported-by: Dusty Mabe <dustymabe@redhat.com>
25Signed-off-by: Lukas Czerner <lczerner@redhat.com>
26Signed-off-by: Theodore Ts'o <tytso@mit.edu>
27
28Upstream-Status: Backport [https://github.com/tytso/e2fsprogs/commit/2c69c94217b6db083d601d4fd62d6ab6c1628fee]
29Signed-off-by: Changqing Li <changqing.li@windriver.com>
30---
31 e2fsck/super.c | 12 ++++++------
32 1 file changed, 6 insertions(+), 6 deletions(-)
33
34diff --git a/e2fsck/super.c b/e2fsck/super.c
35index e1c3f935..31e2ffb2 100644
36--- a/e2fsck/super.c
37+++ b/e2fsck/super.c
38@@ -1038,9 +1038,9 @@ void check_super_block(e2fsck_t ctx)
39 * Check to see if the superblock last mount time or last
40 * write time is in the future.
41 */
42- if (!broken_system_clock && fs->super->s_checkinterval &&
43- !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
44- fs->super->s_mtime > (__u32) ctx->now) {
45+ if (((ctx->options & E2F_OPT_FORCE) || fs->super->s_checkinterval) &&
46+ !broken_system_clock && !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
47+ (fs->super->s_mtime > (__u32) ctx->now)) {
48 pctx.num = fs->super->s_mtime;
49 problem = PR_0_FUTURE_SB_LAST_MOUNT;
50 if (fs->super->s_mtime <= (__u32) ctx->now + ctx->time_fudge)
51@@ -1050,9 +1050,9 @@ void check_super_block(e2fsck_t ctx)
52 fs->flags |= EXT2_FLAG_DIRTY;
53 }
54 }
55- if (!broken_system_clock && fs->super->s_checkinterval &&
56- !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
57- fs->super->s_wtime > (__u32) ctx->now) {
58+ if (((ctx->options & E2F_OPT_FORCE) || fs->super->s_checkinterval) &&
59+ !broken_system_clock && !(ctx->flags & E2F_FLAG_TIME_INSANE) &&
60+ (fs->super->s_wtime > (__u32) ctx->now)) {
61 pctx.num = fs->super->s_wtime;
62 problem = PR_0_FUTURE_SB_LAST_WRITE;
63 if (fs->super->s_wtime <= (__u32) ctx->now + ctx->time_fudge)
64--
652.25.1
66
diff --git a/meta/recipes-devtools/gcc/gcc-10.2.inc b/meta/recipes-devtools/gcc/gcc-10.3.inc
index 248e002106..1fdfcced8e 100644
--- a/meta/recipes-devtools/gcc/gcc-10.2.inc
+++ b/meta/recipes-devtools/gcc/gcc-10.3.inc
@@ -2,11 +2,11 @@ require gcc-common.inc
2 2
3# Third digit in PV should be incremented after a minor release 3# Third digit in PV should be incremented after a minor release
4 4
5PV = "10.2.0" 5PV = "10.3.0"
6 6
7# BINV should be incremented to a revision after a minor gcc release 7# BINV should be incremented to a revision after a minor gcc release
8 8
9BINV = "10.2.0" 9BINV = "10.3.0"
10 10
11FILESEXTRAPATHS =. "${FILE_DIRNAME}/gcc:${FILE_DIRNAME}/gcc/backport:" 11FILESEXTRAPATHS =. "${FILE_DIRNAME}/gcc:${FILE_DIRNAME}/gcc/backport:"
12 12
@@ -65,17 +65,18 @@ SRC_URI = "\
65 file://0035-gentypes-genmodes-Do-not-use-__LINE__-for-maintainin.patch \ 65 file://0035-gentypes-genmodes-Do-not-use-__LINE__-for-maintainin.patch \
66 file://0036-mingw32-Enable-operation_not_supported.patch \ 66 file://0036-mingw32-Enable-operation_not_supported.patch \
67 file://0037-libatomic-Do-not-enforce-march-on-aarch64.patch \ 67 file://0037-libatomic-Do-not-enforce-march-on-aarch64.patch \
68 file://0001-aarch64-New-Straight-Line-Speculation-SLS-mitigation.patch \
69 file://0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch \
70 file://0003-aarch64-Mitigate-SLS-for-BLR-instruction.patch \
71 file://0001-aarch64-Fix-up-__aarch64_cas16_acq_rel-fallback.patch \
72 file://0001-libatomic-libgomp-libitc-Fix-bootstrap-PR70454.patch \ 68 file://0001-libatomic-libgomp-libitc-Fix-bootstrap-PR70454.patch \
73 file://0001-CVE-2021-35465.patch \ 69 file://0001-CVE-2021-35465.patch \
74 file://0002-CVE-2021-35465.patch \ 70 file://0002-CVE-2021-35465.patch \
75 file://0003-CVE-2021-35465.patch \ 71 file://0003-CVE-2021-35465.patch \
76 file://0004-CVE-2021-35465.patch \ 72 file://0004-CVE-2021-35465.patch \
73 file://0001-CVE-2021-42574.patch \
74 file://0002-CVE-2021-42574.patch \
75 file://0003-CVE-2021-42574.patch \
76 file://0004-CVE-2021-42574.patch \
77 file://0005-CVE-2021-42574.patch \
77" 78"
78SRC_URI[sha256sum] = "b8dd4368bb9c7f0b98188317ee0254dd8cc99d1e3a18d0ff146c855fe16c1d8c" 79SRC_URI[sha256sum] = "64f404c1a650f27fc33da242e1f2df54952e3963a49e06e73f6940f3223ac344"
79 80
80S = "${TMPDIR}/work-shared/gcc-${PV}-${PR}/gcc-${PV}" 81S = "${TMPDIR}/work-shared/gcc-${PV}-${PR}/gcc-${PV}"
81# For dev release snapshotting 82# For dev release snapshotting
@@ -122,3 +123,6 @@ EXTRA_OECONF_PATHS = "\
122 --with-sysroot=/not/exist \ 123 --with-sysroot=/not/exist \
123 --with-build-sysroot=${STAGING_DIR_TARGET} \ 124 --with-build-sysroot=${STAGING_DIR_TARGET} \
124" 125"
126
127# Is a binutils 2.26 issue, not gcc
128CVE_CHECK_WHITELIST += "CVE-2021-37322"
diff --git a/meta/recipes-devtools/gcc/gcc-cross-canadian_10.2.bb b/meta/recipes-devtools/gcc/gcc-cross-canadian_10.3.bb
index bf53c5cd78..bf53c5cd78 100644
--- a/meta/recipes-devtools/gcc/gcc-cross-canadian_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-cross-canadian_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-cross_10.2.bb b/meta/recipes-devtools/gcc/gcc-cross_10.3.bb
index b43cca0c52..b43cca0c52 100644
--- a/meta/recipes-devtools/gcc/gcc-cross_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-cross_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-crosssdk_10.2.bb b/meta/recipes-devtools/gcc/gcc-crosssdk_10.3.bb
index 40a6c4feff..40a6c4feff 100644
--- a/meta/recipes-devtools/gcc/gcc-crosssdk_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-crosssdk_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-runtime_10.2.bb b/meta/recipes-devtools/gcc/gcc-runtime_10.3.bb
index dd430b57eb..dd430b57eb 100644
--- a/meta/recipes-devtools/gcc/gcc-runtime_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-runtime_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-sanitizers_10.2.bb b/meta/recipes-devtools/gcc/gcc-sanitizers_10.3.bb
index f3c7058114..f3c7058114 100644
--- a/meta/recipes-devtools/gcc/gcc-sanitizers_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-sanitizers_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc-source_10.2.bb b/meta/recipes-devtools/gcc/gcc-source_10.3.bb
index b890fa33ea..b890fa33ea 100644
--- a/meta/recipes-devtools/gcc/gcc-source_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc-source_10.3.bb
diff --git a/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-35465.patch b/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-35465.patch
index b9bca49dd8..4d7c7e3f18 100644
--- a/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-35465.patch
+++ b/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-35465.patch
@@ -33,7 +33,7 @@ Signed-off-by: Pgowda <pgowda.cve@gmail.com>
33diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c 33diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
34--- a/gcc/config/arm/arm.c 2020-07-22 23:35:17.344384552 -0700 34--- a/gcc/config/arm/arm.c 2020-07-22 23:35:17.344384552 -0700
35+++ b/gcc/config/arm/arm.c 2021-11-11 20:16:19.761241867 -0800 35+++ b/gcc/config/arm/arm.c 2021-11-11 20:16:19.761241867 -0800
36@@ -3595,6 +3595,15 @@ arm_option_override (void) 36@@ -3610,6 +3610,15 @@ arm_option_override (void)
37 fix_cm3_ldrd = 0; 37 fix_cm3_ldrd = 0;
38 } 38 }
39 39
@@ -52,7 +52,7 @@ diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
52diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in 52diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
53--- a/gcc/config/arm/arm-cpus.in 2020-07-22 23:35:17.340384509 -0700 53--- a/gcc/config/arm/arm-cpus.in 2020-07-22 23:35:17.340384509 -0700
54+++ b/gcc/config/arm/arm-cpus.in 2021-11-11 20:17:01.364573561 -0800 54+++ b/gcc/config/arm/arm-cpus.in 2021-11-11 20:17:01.364573561 -0800
55@@ -190,6 +190,9 @@ define feature quirk_armv6kz 55@@ -186,6 +186,9 @@ define feature quirk_armv6kz
56 # Cortex-M3 LDRD quirk. 56 # Cortex-M3 LDRD quirk.
57 define feature quirk_cm3_ldrd 57 define feature quirk_cm3_ldrd
58 58
@@ -62,7 +62,7 @@ diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
62 # Don't use .cpu assembly directive 62 # Don't use .cpu assembly directive
63 define feature quirk_no_asmcpu 63 define feature quirk_no_asmcpu
64 64
65@@ -314,7 +317,7 @@ define fgroup DOTPROD NEON dotprod 65@@ -322,7 +325,7 @@ define implied vfp_base MVE MVE_FP ALL_F
66 # architectures. 66 # architectures.
67 # xscale isn't really a 'quirk', but it isn't an architecture either and we 67 # xscale isn't really a 'quirk', but it isn't an architecture either and we
68 # need to ignore it for matching purposes. 68 # need to ignore it for matching purposes.
@@ -71,7 +71,7 @@ diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
71 71
72 # Architecture entries 72 # Architecture entries
73 # format: 73 # format:
74@@ -1492,6 +1495,7 @@ begin cpu cortex-m33 74@@ -1524,6 +1527,7 @@ begin cpu cortex-m33
75 architecture armv8-m.main+dsp+fp 75 architecture armv8-m.main+dsp+fp
76 option nofp remove ALL_FP 76 option nofp remove ALL_FP
77 option nodsp remove armv7em 77 option nodsp remove armv7em
@@ -79,7 +79,7 @@ diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
79 costs v7m 79 costs v7m
80 end cpu cortex-m33 80 end cpu cortex-m33
81 81
82@@ -1501,6 +1505,7 @@ begin cpu cortex-m35p 82@@ -1533,6 +1537,7 @@ begin cpu cortex-m35p
83 architecture armv8-m.main+dsp+fp 83 architecture armv8-m.main+dsp+fp
84 option nofp remove ALL_FP 84 option nofp remove ALL_FP
85 option nodsp remove armv7em 85 option nodsp remove armv7em
@@ -87,10 +87,10 @@ diff --git a/gcc/config/arm/arm-cpus.in b/gcc/config/arm/arm-cpus.in
87 costs v7m 87 costs v7m
88 end cpu cortex-m35p 88 end cpu cortex-m35p
89 89
90@@ -1508,7 +1513,7 @@ begin cpu cortex-m55 90@@ -1544,7 +1549,7 @@ begin cpu cortex-m55
91 cname cortexm55 91 option nomve remove mve mve_float
92 tune flags LDSCHED 92 option nofp remove ALL_FP mve_float
93 architecture armv8.1-m.main+mve.fp+fp.dp 93 option nodsp remove MVE mve_float
94- isa quirk_no_asmcpu 94- isa quirk_no_asmcpu
95+ isa quirk_no_asmcpu quirk_vlldm 95+ isa quirk_no_asmcpu quirk_vlldm
96 costs v7m 96 costs v7m
@@ -113,7 +113,7 @@ diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
113diff -upr a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi 113diff -upr a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
114--- a/gcc/doc/invoke.texi 2021-11-11 19:30:56.264523105 -0800 114--- a/gcc/doc/invoke.texi 2021-11-11 19:30:56.264523105 -0800
115+++ b/gcc/doc/invoke.texi 2021-11-11 20:16:19.769241739 -0800 115+++ b/gcc/doc/invoke.texi 2021-11-11 20:16:19.769241739 -0800
116@@ -773,6 +773,7 @@ Objective-C and Objective-C++ Dialects}. 116@@ -774,6 +774,7 @@ Objective-C and Objective-C++ Dialects}.
117 -mverbose-cost-dump @gol 117 -mverbose-cost-dump @gol
118 -mpure-code @gol 118 -mpure-code @gol
119 -mcmse @gol 119 -mcmse @gol
@@ -121,7 +121,7 @@ diff -upr a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
121 -mfdpic} 121 -mfdpic}
122 122
123 @emph{AVR Options} 123 @emph{AVR Options}
124@@ -21233,6 +21234,14 @@ Use multiply and add/subtract instructio 124@@ -21266,6 +21267,14 @@ Use multiply and add/subtract instructio
125 125
126 Do not use multiply and add/subtract instructions. 126 Do not use multiply and add/subtract instructions.
127 127
diff --git a/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-42574.patch
new file mode 100644
index 0000000000..e0f4f7d32f
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0001-CVE-2021-42574.patch
@@ -0,0 +1,2906 @@
1From 004bb936d6d5f177af26ad4905595e843d5665a5 Mon Sep 17 00:00:00 2001
2From: Lewis Hyatt <lhyatt@gmail.com>
3Date: Tue, 14 Jul 2020 12:05:56 -0400
4Subject: [PATCH] diagnostics: Support conversion of tabs to spaces [PR49973]
5 [PR86904]
6
7Supports conversion of tabs to spaces when outputting diagnostics. Also
8adds -fdiagnostics-column-unit and -fdiagnostics-column-origin options to
9control how the column number is output, thereby resolving the two PRs.
10
11gcc/c-family/ChangeLog:
12
13 PR other/86904
14 * c-indentation.c (should_warn_for_misleading_indentation): Get
15 global tabstop from the new source.
16 * c-opts.c (c_common_handle_option): Remove handling of -ftabstop, which
17 is now a common option.
18 * c.opt: Likewise.
19
20gcc/ChangeLog:
21
22 PR preprocessor/49973
23 PR other/86904
24 * common.opt: Handle -ftabstop here instead of in c-family
25 options. Add -fdiagnostics-column-unit= and
26 -fdiagnostics-column-origin= options.
27 * opts.c (common_handle_option): Handle the new options.
28 * diagnostic-format-json.cc (json_from_expanded_location): Add
29 diagnostic_context argument. Use it to convert column numbers as per
30 the new options.
31 (json_from_location_range): Likewise.
32 (json_from_fixit_hint): Likewise.
33 (json_end_diagnostic): Pass the new context argument to helper
34 functions above. Add "column-origin" field to the output.
35 (test_unknown_location): Add the new context argument to calls to
36 helper functions.
37 (test_bad_endpoints): Likewise.
38 * diagnostic-show-locus.c
39 (exploc_with_display_col::exploc_with_display_col): Support
40 tabstop parameter.
41 (layout_point::layout_point): Make use of class
42 exploc_with_display_col.
43 (layout_range::layout_range): Likewise.
44 (struct line_bounds): Clarify that the units are now always
45 display columns. Rename members accordingly. Add constructor.
46 (layout::print_source_line): Add support for tab expansion.
47 (make_range): Adapt to class layout_range changes.
48 (layout::maybe_add_location_range): Likewise.
49 (layout::layout): Adapt to class exploc_with_display_col changes.
50 (layout::calculate_x_offset_display): Support tabstop parameter.
51 (layout::print_annotation_line): Adapt to struct line_bounds changes.
52 (layout::print_line): Likewise.
53 (line_label::line_label): Add diagnostic_context argument.
54 (get_affected_range): Likewise.
55 (get_printed_columns): Likewise.
56 (layout::print_any_labels): Adapt to struct line_label changes.
57 (class correction): Add m_tabstop member.
58 (correction::correction): Add tabstop argument.
59 (correction::compute_display_cols): Use m_tabstop.
60 (class line_corrections): Add m_context member.
61 (line_corrections::line_corrections): Add diagnostic_context argument.
62 (line_corrections::add_hint): Use m_context to handle tabstops.
63 (layout::print_trailing_fixits): Adapt to class line_corrections
64 changes.
65 (test_layout_x_offset_display_utf8): Support tabstop parameter.
66 (test_layout_x_offset_display_tab): New selftest.
67 (test_one_liner_colorized_utf8): Likewise.
68 (test_tab_expansion): Likewise.
69 (test_diagnostic_show_locus_one_liner_utf8): Call the new tests.
70 (diagnostic_show_locus_c_tests): Likewise.
71 (test_overlapped_fixit_printing): Adapt to helper class and
72 function changes.
73 (test_overlapped_fixit_printing_utf8): Likewise.
74 (test_overlapped_fixit_printing_2): Likewise.
75 * diagnostic.h (enum diagnostics_column_unit): New enum.
76 (struct diagnostic_context): Add members for the new options.
77 (diagnostic_converted_column): Declare.
78 (json_from_expanded_location): Add new context argument.
79 * diagnostic.c (diagnostic_initialize): Initialize new members.
80 (diagnostic_converted_column): New function.
81 (maybe_line_and_column): Be willing to output a column of 0.
82 (diagnostic_get_location_text): Convert column number as per the new
83 options.
84 (diagnostic_report_current_module): Likewise.
85 (assert_location_text): Add origin and column_unit arguments for
86 testing the new functionality.
87 (test_diagnostic_get_location_text): Test the new functionality.
88 * doc/invoke.texi: Document the new options and behavior.
89 * input.h (location_compute_display_column): Add tabstop argument.
90 * input.c (location_compute_display_column): Likewise.
91 (test_cpp_utf8): Add selftests for tab expansion.
92 * tree-diagnostic-path.cc (default_tree_make_json_for_path): Pass the
93 new context argument to json_from_expanded_location().
94
95libcpp/ChangeLog:
96
97 PR preprocessor/49973
98 PR other/86904
99 * include/cpplib.h (struct cpp_options): Removed support for -ftabstop,
100 which is now handled by diagnostic_context.
101 (class cpp_display_width_computation): New class.
102 (cpp_byte_column_to_display_column): Add optional tabstop argument.
103 (cpp_display_width): Likewise.
104 (cpp_display_column_to_byte_column): Likewise.
105 * charset.c
106 (cpp_display_width_computation::cpp_display_width_computation): New
107 function.
108 (cpp_display_width_computation::advance_display_cols): Likewise.
109 (compute_next_display_width): Removed and implemented this
110 functionality in a new function...
111 (cpp_display_width_computation::process_next_codepoint): ...here.
112 (cpp_byte_column_to_display_column): Added tabstop argument.
113 Reimplemented in terms of class cpp_display_width_computation.
114 (cpp_display_column_to_byte_column): Likewise.
115 * init.c (cpp_create_reader): Remove handling of -ftabstop, which is now
116 handled by diagnostic_context.
117
118gcc/testsuite/ChangeLog:
119
120 PR preprocessor/49973
121 PR other/86904
122 * c-c++-common/Wmisleading-indentation-3.c: Adjust expected output
123 for new defaults.
124 * c-c++-common/Wmisleading-indentation.c: Likewise.
125 * c-c++-common/diagnostic-format-json-1.c: Likewise.
126 * c-c++-common/diagnostic-format-json-2.c: Likewise.
127 * c-c++-common/diagnostic-format-json-3.c: Likewise.
128 * c-c++-common/diagnostic-format-json-4.c: Likewise.
129 * c-c++-common/diagnostic-format-json-5.c: Likewise.
130 * c-c++-common/missing-close-symbol.c: Likewise.
131 * g++.dg/diagnostic/bad-binary-ops.C: Likewise.
132 * g++.dg/parse/error4.C: Likewise.
133 * g++.old-deja/g++.brendan/crash11.C: Likewise.
134 * g++.old-deja/g++.pt/overload2.C: Likewise.
135 * g++.old-deja/g++.robertl/eb109.C: Likewise.
136 * gcc.dg/analyzer/malloc-paths-9.c: Likewise.
137 * gcc.dg/bad-binary-ops.c: Likewise.
138 * gcc.dg/format/branch-1.c: Likewise.
139 * gcc.dg/format/pr79210.c: Likewise.
140 * gcc.dg/plugin/diagnostic-test-expressions-1.c: Likewise.
141 * gcc.dg/plugin/diagnostic-test-string-literals-1.c: Likewise.
142 * gcc.dg/redecl-4.c: Likewise.
143 * gfortran.dg/diagnostic-format-json-1.F90: Likewise.
144 * gfortran.dg/diagnostic-format-json-2.F90: Likewise.
145 * gfortran.dg/diagnostic-format-json-3.F90: Likewise.
146 * go.dg/arrayclear.go: Add a comment explaining why adding a
147 comment was necessary to work around a dejagnu bug.
148 * c-c++-common/diagnostic-units-1.c: New test.
149 * c-c++-common/diagnostic-units-2.c: New test.
150 * c-c++-common/diagnostic-units-3.c: New test.
151 * c-c++-common/diagnostic-units-4.c: New test.
152 * c-c++-common/diagnostic-units-5.c: New test.
153 * c-c++-common/diagnostic-units-6.c: New test.
154 * c-c++-common/diagnostic-units-7.c: New test.
155 * c-c++-common/diagnostic-units-8.c: New test.
156
157CVE: CVE-2021-42574
158Upstream-Status: Backport [https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=004bb936d6d5f177af26ad4905595e843d5665a5]
159Signed-off-by: Pgowda <pgowda.cve@gmail.com>
160---
161 gcc/c-family/c-indentation.c | 5 +-
162 gcc/c-family/c-opts.c | 6 -
163 gcc/c-family/c.opt | 4 -
164 gcc/common.opt | 21 +
165 gcc/diagnostic-format-json.cc | 55 +-
166 gcc/diagnostic-show-locus.c | 504 +++++++++++++-----
167 gcc/diagnostic.c | 113 +++-
168 gcc/diagnostic.h | 28 +-
169 gcc/doc/invoke.texi | 68 ++-
170 gcc/input.c | 72 ++-
171 gcc/input.h | 4 +-
172 gcc/opts.c | 14 +
173 .../c-c++-common/Wmisleading-indentation-3.c | 12 +-
174 .../c-c++-common/Wmisleading-indentation.c | 6 +-
175 .../c-c++-common/diagnostic-format-json-1.c | 5 +
176 .../c-c++-common/diagnostic-format-json-2.c | 5 +
177 .../c-c++-common/diagnostic-format-json-3.c | 5 +
178 .../c-c++-common/diagnostic-format-json-4.c | 9 +
179 .../c-c++-common/diagnostic-format-json-5.c | 9 +
180 .../c-c++-common/diagnostic-units-1.c | 28 +
181 .../c-c++-common/diagnostic-units-2.c | 28 +
182 .../c-c++-common/diagnostic-units-3.c | 28 +
183 .../c-c++-common/diagnostic-units-4.c | 28 +
184 .../c-c++-common/diagnostic-units-5.c | 28 +
185 .../c-c++-common/diagnostic-units-6.c | 28 +
186 .../c-c++-common/diagnostic-units-7.c | 28 +
187 .../c-c++-common/diagnostic-units-8.c | 28 +
188 .../c-c++-common/missing-close-symbol.c | 6 +-
189 .../g++.dg/diagnostic/bad-binary-ops.C | 8 +-
190 gcc/testsuite/g++.dg/parse/error4.C | 2 +-
191 .../g++.old-deja/g++.brendan/crash11.C | 4 +-
192 gcc/testsuite/g++.old-deja/g++.pt/overload2.C | 2 +-
193 .../g++.old-deja/g++.robertl/eb109.C | 4 +-
194 .../gcc.dg/analyzer/malloc-paths-9.c | 2 +-
195 gcc/testsuite/gcc.dg/bad-binary-ops.c | 8 +-
196 gcc/testsuite/gcc.dg/format/branch-1.c | 2 +-
197 gcc/testsuite/gcc.dg/format/pr79210.c | 2 +-
198 .../plugin/diagnostic-test-expressions-1.c | 16 +-
199 .../diagnostic-test-string-literals-1.c | 4 +-
200 gcc/testsuite/gcc.dg/redecl-4.c | 2 +-
201 .../gfortran.dg/diagnostic-format-json-1.F90 | 5 +
202 .../gfortran.dg/diagnostic-format-json-2.F90 | 5 +
203 .../gfortran.dg/diagnostic-format-json-3.F90 | 5 +
204 gcc/testsuite/go.dg/arrayclear.go | 3 +
205 gcc/tree-diagnostic-path.cc | 5 +-
206 libcpp/charset.c | 98 ++--
207 libcpp/include/cpplib.h | 40 +-
208 libcpp/init.c | 1 -
209 48 files changed, 1106 insertions(+), 287 deletions(-)
210 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-1.c
211 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-2.c
212 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-3.c
213 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-4.c
214 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-5.c
215 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-6.c
216 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-7.c
217 create mode 100644 gcc/testsuite/c-c++-common/diagnostic-units-8.c
218
219diff --git a/gcc/c-family/c-indentation.c b/gcc/c-family/c-indentation.c
220--- a/gcc/c-family/c-indentation.c 2020-07-22 23:35:17.296384022 -0700
221+++ b/gcc/c-family/c-indentation.c 2021-12-25 01:20:53.475636694 -0800
222@@ -24,8 +24,7 @@ along with GCC; see the file COPYING3.
223 #include "c-common.h"
224 #include "c-indentation.h"
225 #include "selftest.h"
226-
227-extern cpp_options *cpp_opts;
228+#include "diagnostic.h"
229
230 /* Round up VIS_COLUMN to nearest tab stop. */
231
232@@ -294,7 +293,7 @@ should_warn_for_misleading_indentation (
233 expanded_location next_stmt_exploc = expand_location (next_stmt_loc);
234 expanded_location guard_exploc = expand_location (guard_loc);
235
236- const unsigned int tab_width = cpp_opts->tabstop;
237+ const unsigned int tab_width = global_dc->tabstop;
238
239 /* They must be in the same file. */
240 if (next_stmt_exploc.file != body_exploc.file)
241diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
242--- a/gcc/c-family/c.opt 2021-12-24 20:23:42.816809230 -0800
243+++ b/gcc/c-family/c.opt 2021-12-25 01:20:53.475636694 -0800
244@@ -1876,10 +1876,6 @@ Enum(strong_eval_order) String(some) Val
245 EnumValue
246 Enum(strong_eval_order) String(all) Value(2)
247
248-ftabstop=
249-C ObjC C++ ObjC++ Joined RejectNegative UInteger
250--ftabstop=<number> Distance between tab stops for column reporting.
251-
252 ftemplate-backtrace-limit=
253 C++ ObjC++ Joined RejectNegative UInteger Var(template_backtrace_limit) Init(10)
254 Set the maximum number of template instantiation notes for a single warning or error.
255diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
256--- a/gcc/c-family/c-opts.c 2021-12-24 20:23:44.824774786 -0800
257+++ b/gcc/c-family/c-opts.c 2021-12-25 01:20:53.475636694 -0800
258@@ -504,12 +504,6 @@ c_common_handle_option (size_t scode, co
259 cpp_opts->track_macro_expansion = 2;
260 break;
261
262- case OPT_ftabstop_:
263- /* It is documented that we silently ignore silly values. */
264- if (value >= 1 && value <= 100)
265- cpp_opts->tabstop = value;
266- break;
267-
268 case OPT_fexec_charset_:
269 cpp_opts->narrow_charset = arg;
270 break;
271diff --git a/gcc/common.opt b/gcc/common.opt
272--- a/gcc/common.opt 2021-12-24 20:23:42.480814993 -0800
273+++ b/gcc/common.opt 2021-12-25 01:20:53.475636694 -0800
274@@ -1325,6 +1325,14 @@ Enum(diagnostic_url_rule) String(always)
275 EnumValue
276 Enum(diagnostic_url_rule) String(auto) Value(DIAGNOSTICS_URL_AUTO)
277
278+fdiagnostics-column-unit=
279+Common Joined RejectNegative Enum(diagnostics_column_unit)
280+-fdiagnostics-column-unit=[display|byte] Select whether column numbers are output as display columns (default) or raw bytes.
281+
282+fdiagnostics-column-origin=
283+Common Joined RejectNegative UInteger
284+-fdiagnostics-column-origin=<number> Set the number of the first column. The default is 1-based as per GNU style, but some utilities may expect 0-based, for example.
285+
286 fdiagnostics-format=
287 Common Joined RejectNegative Enum(diagnostics_output_format)
288 -fdiagnostics-format=[text|json] Select output format.
289@@ -1334,6 +1342,15 @@ SourceInclude
290 diagnostic.h
291
292 Enum
293+Name(diagnostics_column_unit) Type(int)
294+
295+EnumValue
296+Enum(diagnostics_column_unit) String(display) Value(DIAGNOSTICS_COLUMN_UNIT_DISPLAY)
297+
298+EnumValue
299+Enum(diagnostics_column_unit) String(byte) Value(DIAGNOSTICS_COLUMN_UNIT_BYTE)
300+
301+Enum
302 Name(diagnostics_output_format) Type(int)
303
304 EnumValue
305@@ -1362,6 +1379,10 @@ fdiagnostics-path-format=
306 Common Joined RejectNegative Var(flag_diagnostics_path_format) Enum(diagnostic_path_format) Init(DPF_INLINE_EVENTS)
307 Specify how to print any control-flow path associated with a diagnostic.
308
309+ftabstop=
310+Common Joined RejectNegative UInteger
311+-ftabstop=<number> Distance between tab stops for column reporting.
312+
313 Enum
314 Name(diagnostic_path_format) Type(int)
315
316diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
317--- a/gcc/diagnostic.c 2020-07-22 23:35:17.556386887 -0700
318+++ b/gcc/diagnostic.c 2021-12-25 01:23:41.300841207 -0800
319@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3.
320 #include "selftest.h"
321 #include "selftest-diagnostic.h"
322 #include "opts.h"
323+#include "cpplib.h"
324
325 #ifdef HAVE_TERMIOS_H
326 # include <termios.h>
327@@ -219,6 +220,9 @@ diagnostic_initialize (diagnostic_contex
328 context->min_margin_width = 0;
329 context->show_ruler_p = false;
330 context->parseable_fixits_p = false;
331+ context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
332+ context->column_origin = 1;
333+ context->tabstop = 8;
334 context->edit_context_ptr = NULL;
335 context->diagnostic_group_nesting_depth = 0;
336 context->diagnostic_group_emission_count = 0;
337@@ -353,8 +357,51 @@ diagnostic_get_color_for_kind (diagnosti
338 return diagnostic_kind_color[kind];
339 }
340
341+/* Given an expanded_location, convert the column (which is in 1-based bytes)
342+ to the requested units, without converting the origin.
343+ Return -1 if the column is invalid (<= 0). */
344+
345+static int
346+convert_column_unit (enum diagnostics_column_unit column_unit,
347+ int tabstop,
348+ expanded_location s)
349+{
350+ if (s.column <= 0)
351+ return -1;
352+
353+ switch (column_unit)
354+ {
355+ default:
356+ gcc_unreachable ();
357+
358+ case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
359+ {
360+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
361+ return location_compute_display_column (s, policy);
362+ }
363+
364+ case DIAGNOSTICS_COLUMN_UNIT_BYTE:
365+ return s.column;
366+ }
367+}
368+
369+/* Given an expanded_location, convert the column (which is in 1-based bytes)
370+ to the requested units and origin. Return -1 if the column is
371+ invalid (<= 0). */
372+int
373+diagnostic_converted_column (diagnostic_context *context, expanded_location s)
374+{
375+ int one_based_col
376+ = convert_column_unit (context->column_unit, context->tabstop, s);
377+ if (one_based_col <= 0)
378+ return -1;
379+ return one_based_col + (context->column_origin - 1);
380+}
381+
382 /* Return a formatted line and column ':%line:%column'. Elided if
383- zero. The result is a statically allocated buffer. */
384+ line == 0 or col < 0. (A column of 0 may be valid due to the
385+ -fdiagnostics-column-origin option.)
386+ The result is a statically allocated buffer. */
387
388 static const char *
389 maybe_line_and_column (int line, int col)
390@@ -363,8 +410,9 @@ maybe_line_and_column (int line, int col
391
392 if (line)
393 {
394- size_t l = snprintf (result, sizeof (result),
395- col ? ":%d:%d" : ":%d", line, col);
396+ size_t l
397+ = snprintf (result, sizeof (result),
398+ col >= 0 ? ":%d:%d" : ":%d", line, col);
399 gcc_checking_assert (l < sizeof (result));
400 }
401 else
402@@ -383,8 +431,14 @@ diagnostic_get_location_text (diagnostic
403 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
404 const char *locus_ce = colorize_stop (pp_show_color (pp));
405 const char *file = s.file ? s.file : progname;
406- int line = strcmp (file, N_("<built-in>")) ? s.line : 0;
407- int col = context->show_column ? s.column : 0;
408+ int line = 0;
409+ int col = -1;
410+ if (strcmp (file, N_("<built-in>")))
411+ {
412+ line = s.line;
413+ if (context->show_column)
414+ col = diagnostic_converted_column (context, s);
415+ }
416
417 const char *line_col = maybe_line_and_column (line, col);
418 return build_message_string ("%s%s%s:%s", locus_cs, file,
419@@ -650,14 +704,20 @@ diagnostic_report_current_module (diagno
420 if (! MAIN_FILE_P (map))
421 {
422 bool first = true;
423+ expanded_location s = {};
424 do
425 {
426 where = linemap_included_from (map);
427 map = linemap_included_from_linemap (line_table, map);
428- const char *line_col
429- = maybe_line_and_column (SOURCE_LINE (map, where),
430- first && context->show_column
431- ? SOURCE_COLUMN (map, where) : 0);
432+ s.file = LINEMAP_FILE (map);
433+ s.line = SOURCE_LINE (map, where);
434+ int col = -1;
435+ if (first && context->show_column)
436+ {
437+ s.column = SOURCE_COLUMN (map, where);
438+ col = diagnostic_converted_column (context, s);
439+ }
440+ const char *line_col = maybe_line_and_column (s.line, col);
441 static const char *const msgs[] =
442 {
443 N_("In file included from"),
444@@ -666,7 +726,7 @@ diagnostic_report_current_module (diagno
445 unsigned index = !first;
446 pp_verbatim (context->printer, "%s%s %r%s%s%R",
447 first ? "" : ",\n", _(msgs[index]),
448- "locus", LINEMAP_FILE (map), line_col);
449+ "locus", s.file, line_col);
450 first = false;
451 }
452 while (! MAIN_FILE_P (map));
453@@ -2042,10 +2102,15 @@ test_print_parseable_fixits_replace ()
454 static void
455 assert_location_text (const char *expected_loc_text,
456 const char *filename, int line, int column,
457- bool show_column)
458+ bool show_column,
459+ int origin = 1,
460+ enum diagnostics_column_unit column_unit
461+ = DIAGNOSTICS_COLUMN_UNIT_BYTE)
462 {
463 test_diagnostic_context dc;
464 dc.show_column = show_column;
465+ dc.column_unit = column_unit;
466+ dc.column_origin = origin;
467
468 expanded_location xloc;
469 xloc.file = filename;
470@@ -2069,7 +2134,10 @@ test_diagnostic_get_location_text ()
471 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
472 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
473 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
474- assert_location_text ("foo.c:42:", "foo.c", 42, 0, true);
475+ assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
476+ assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
477+ for (int origin = 0; origin != 2; ++origin)
478+ assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
479 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
480 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
481 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
482@@ -2077,6 +2145,41 @@ test_diagnostic_get_location_text ()
483 maybe_line_and_column (INT_MAX, INT_MAX);
484 maybe_line_and_column (INT_MIN, INT_MIN);
485
486+ {
487+ /* In order to test display columns vs byte columns, we need to create a
488+ file for location_get_source_line() to read. */
489+
490+ const char *const content = "smile \xf0\x9f\x98\x82\n";
491+ const int line_bytes = strlen (content) - 1;
492+ const int def_tabstop = 8;
493+ const int display_width = cpp_display_width (content, line_bytes,
494+ def_tabstop);
495+ ASSERT_EQ (line_bytes - 2, display_width);
496+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
497+ const char *const fname = tmp.get_filename ();
498+ const int buf_len = strlen (fname) + 16;
499+ char *const expected = XNEWVEC (char, buf_len);
500+
501+ snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
502+ assert_location_text (expected, fname, 1, line_bytes, true,
503+ 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
504+
505+ snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
506+ assert_location_text (expected, fname, 1, line_bytes, true,
507+ 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
508+
509+ snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
510+ assert_location_text (expected, fname, 1, line_bytes, true,
511+ 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
512+
513+ snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
514+ assert_location_text (expected, fname, 1, line_bytes, true,
515+ 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
516+
517+ XDELETEVEC (expected);
518+ }
519+
520+
521 progname = old_progname;
522 }
523
524diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
525--- a/gcc/diagnostic-format-json.cc 2020-07-22 23:35:17.556386887 -0700
526+++ b/gcc/diagnostic-format-json.cc 2021-12-25 01:20:53.475636694 -0800
527@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.
528 #include "system.h"
529 #include "coretypes.h"
530 #include "diagnostic.h"
531+#include "selftest-diagnostic.h"
532 #include "diagnostic-metadata.h"
533 #include "json.h"
534 #include "selftest.h"
535@@ -43,21 +44,43 @@ static json::array *cur_children_array;
536 /* Generate a JSON object for LOC. */
537
538 json::value *
539-json_from_expanded_location (location_t loc)
540+json_from_expanded_location (diagnostic_context *context, location_t loc)
541 {
542 expanded_location exploc = expand_location (loc);
543 json::object *result = new json::object ();
544 if (exploc.file)
545 result->set ("file", new json::string (exploc.file));
546 result->set ("line", new json::integer_number (exploc.line));
547- result->set ("column", new json::integer_number (exploc.column));
548+
549+ const enum diagnostics_column_unit orig_unit = context->column_unit;
550+ struct
551+ {
552+ const char *name;
553+ enum diagnostics_column_unit unit;
554+ } column_fields[] = {
555+ {"display-column", DIAGNOSTICS_COLUMN_UNIT_DISPLAY},
556+ {"byte-column", DIAGNOSTICS_COLUMN_UNIT_BYTE}
557+ };
558+ int the_column = INT_MIN;
559+ for (int i = 0; i != sizeof column_fields / sizeof (*column_fields); ++i)
560+ {
561+ context->column_unit = column_fields[i].unit;
562+ const int col = diagnostic_converted_column (context, exploc);
563+ result->set (column_fields[i].name, new json::integer_number (col));
564+ if (column_fields[i].unit == orig_unit)
565+ the_column = col;
566+ }
567+ gcc_assert (the_column != INT_MIN);
568+ result->set ("column", new json::integer_number (the_column));
569+ context->column_unit = orig_unit;
570 return result;
571 }
572
573 /* Generate a JSON object for LOC_RANGE. */
574
575 static json::object *
576-json_from_location_range (const location_range *loc_range, unsigned range_idx)
577+json_from_location_range (diagnostic_context *context,
578+ const location_range *loc_range, unsigned range_idx)
579 {
580 location_t caret_loc = get_pure_location (loc_range->m_loc);
581
582@@ -68,13 +91,13 @@ json_from_location_range (const location
583 location_t finish_loc = get_finish (loc_range->m_loc);
584
585 json::object *result = new json::object ();
586- result->set ("caret", json_from_expanded_location (caret_loc));
587+ result->set ("caret", json_from_expanded_location (context, caret_loc));
588 if (start_loc != caret_loc
589 && start_loc != UNKNOWN_LOCATION)
590- result->set ("start", json_from_expanded_location (start_loc));
591+ result->set ("start", json_from_expanded_location (context, start_loc));
592 if (finish_loc != caret_loc
593 && finish_loc != UNKNOWN_LOCATION)
594- result->set ("finish", json_from_expanded_location (finish_loc));
595+ result->set ("finish", json_from_expanded_location (context, finish_loc));
596
597 if (loc_range->m_label)
598 {
599@@ -91,14 +114,14 @@ json_from_location_range (const location
600 /* Generate a JSON object for HINT. */
601
602 static json::object *
603-json_from_fixit_hint (const fixit_hint *hint)
604+json_from_fixit_hint (diagnostic_context *context, const fixit_hint *hint)
605 {
606 json::object *fixit_obj = new json::object ();
607
608 location_t start_loc = hint->get_start_loc ();
609- fixit_obj->set ("start", json_from_expanded_location (start_loc));
610+ fixit_obj->set ("start", json_from_expanded_location (context, start_loc));
611 location_t next_loc = hint->get_next_loc ();
612- fixit_obj->set ("next", json_from_expanded_location (next_loc));
613+ fixit_obj->set ("next", json_from_expanded_location (context, next_loc));
614 fixit_obj->set ("string", new json::string (hint->get_string ()));
615
616 return fixit_obj;
617@@ -190,11 +213,13 @@ json_end_diagnostic (diagnostic_context
618 else
619 {
620 /* Otherwise, make diag_obj be the top-level object within the group;
621- add a "children" array. */
622+ add a "children" array and record the column origin. */
623 toplevel_array->append (diag_obj);
624 cur_group = diag_obj;
625 cur_children_array = new json::array ();
626 diag_obj->set ("children", cur_children_array);
627+ diag_obj->set ("column-origin",
628+ new json::integer_number (context->column_origin));
629 }
630
631 const rich_location *richloc = diagnostic->richloc;
632@@ -205,7 +230,7 @@ json_end_diagnostic (diagnostic_context
633 for (unsigned int i = 0; i < richloc->get_num_locations (); i++)
634 {
635 const location_range *loc_range = richloc->get_range (i);
636- json::object *loc_obj = json_from_location_range (loc_range, i);
637+ json::object *loc_obj = json_from_location_range (context, loc_range, i);
638 if (loc_obj)
639 loc_array->append (loc_obj);
640 }
641@@ -217,7 +242,7 @@ json_end_diagnostic (diagnostic_context
642 for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++)
643 {
644 const fixit_hint *hint = richloc->get_fixit_hint (i);
645- json::object *fixit_obj = json_from_fixit_hint (hint);
646+ json::object *fixit_obj = json_from_fixit_hint (context, hint);
647 fixit_array->append (fixit_obj);
648 }
649 }
650@@ -320,7 +345,8 @@ namespace selftest {
651 static void
652 test_unknown_location ()
653 {
654- delete json_from_expanded_location (UNKNOWN_LOCATION);
655+ test_diagnostic_context dc;
656+ delete json_from_expanded_location (&dc, UNKNOWN_LOCATION);
657 }
658
659 /* Verify that we gracefully handle attempts to serialize bad
660@@ -338,7 +364,8 @@ test_bad_endpoints ()
661 loc_range.m_range_display_kind = SHOW_RANGE_WITH_CARET;
662 loc_range.m_label = NULL;
663
664- json::object *obj = json_from_location_range (&loc_range, 0);
665+ test_diagnostic_context dc;
666+ json::object *obj = json_from_location_range (&dc, &loc_range, 0);
667 /* We should have a "caret" value, but no "start" or "finish" values. */
668 ASSERT_TRUE (obj != NULL);
669 ASSERT_TRUE (obj->get ("caret") != NULL);
670diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
671--- a/gcc/diagnostic.h 2020-07-22 23:35:17.556386887 -0700
672+++ b/gcc/diagnostic.h 2021-12-25 01:20:53.479636627 -0800
673@@ -24,6 +24,20 @@ along with GCC; see the file COPYING3.
674 #include "pretty-print.h"
675 #include "diagnostic-core.h"
676
677+/* An enum for controlling what units to use for the column number
678+ when diagnostics are output, used by the -fdiagnostics-column-unit option.
679+ Tabs will be expanded or not according to the value of -ftabstop. The origin
680+ (default 1) is controlled by -fdiagnostics-column-origin. */
681+
682+enum diagnostics_column_unit
683+{
684+ /* The default from GCC 11 onwards: display columns. */
685+ DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
686+
687+ /* The behavior in GCC 10 and earlier: simple bytes. */
688+ DIAGNOSTICS_COLUMN_UNIT_BYTE
689+};
690+
691 /* Enum for overriding the standard output format. */
692
693 enum diagnostics_output_format
694@@ -280,6 +294,15 @@ struct diagnostic_context
695 rest of the diagnostic. */
696 bool parseable_fixits_p;
697
698+ /* What units to use when outputting the column number. */
699+ enum diagnostics_column_unit column_unit;
700+
701+ /* The origin for the column number (1-based or 0-based typically). */
702+ int column_origin;
703+
704+ /* The size of the tabstop for tab expansion. */
705+ int tabstop;
706+
707 /* If non-NULL, an edit_context to which fix-it hints should be
708 applied, for generating patches. */
709 edit_context *edit_context_ptr;
710@@ -458,6 +481,8 @@ diagnostic_same_line (const diagnostic_c
711 }
712
713 extern const char *diagnostic_get_color_for_kind (diagnostic_t kind);
714+extern int diagnostic_converted_column (diagnostic_context *context,
715+ expanded_location s);
716
717 /* Pure text formatting support functions. */
718 extern char *file_name_as_prefix (diagnostic_context *, const char *);
719@@ -470,6 +495,7 @@ extern void diagnostic_output_format_ini
720 /* Compute the number of digits in the decimal representation of an integer. */
721 extern int num_digits (int);
722
723-extern json::value *json_from_expanded_location (location_t loc);
724+extern json::value *json_from_expanded_location (diagnostic_context *context,
725+ location_t loc);
726
727 #endif /* ! GCC_DIAGNOSTIC_H */
728diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
729--- a/gcc/diagnostic-show-locus.c 2020-07-22 23:35:17.556386887 -0700
730+++ b/gcc/diagnostic-show-locus.c 2021-12-25 01:20:53.479636627 -0800
731@@ -175,9 +175,10 @@ enum column_unit {
732 class exploc_with_display_col : public expanded_location
733 {
734 public:
735- exploc_with_display_col (const expanded_location &exploc)
736+ exploc_with_display_col (const expanded_location &exploc, int tabstop)
737 : expanded_location (exploc),
738- m_display_col (location_compute_display_column (exploc)) {}
739+ m_display_col (location_compute_display_column (exploc, tabstop))
740+ {}
741
742 int m_display_col;
743 };
744@@ -189,11 +190,11 @@ class exploc_with_display_col : public e
745 class layout_point
746 {
747 public:
748- layout_point (const expanded_location &exploc)
749+ layout_point (const exploc_with_display_col &exploc)
750 : m_line (exploc.line)
751 {
752 m_columns[CU_BYTES] = exploc.column;
753- m_columns[CU_DISPLAY_COLS] = location_compute_display_column (exploc);
754+ m_columns[CU_DISPLAY_COLS] = exploc.m_display_col;
755 }
756
757 linenum_type m_line;
758@@ -205,10 +206,10 @@ class layout_point
759 class layout_range
760 {
761 public:
762- layout_range (const expanded_location *start_exploc,
763- const expanded_location *finish_exploc,
764+ layout_range (const exploc_with_display_col &start_exploc,
765+ const exploc_with_display_col &finish_exploc,
766 enum range_display_kind range_display_kind,
767- const expanded_location *caret_exploc,
768+ const exploc_with_display_col &caret_exploc,
769 unsigned original_idx,
770 const range_label *label);
771
772@@ -226,22 +227,18 @@ class layout_range
773
774 /* A struct for use by layout::print_source_line for telling
775 layout::print_annotation_line the extents of the source line that
776- it printed, so that underlines can be clipped appropriately. */
777+ it printed, so that underlines can be clipped appropriately. Units
778+ are 1-based display columns. */
779
780 struct line_bounds
781 {
782- int m_first_non_ws;
783- int m_last_non_ws;
784+ int m_first_non_ws_disp_col;
785+ int m_last_non_ws_disp_col;
786
787- void convert_to_display_cols (char_span line)
788+ line_bounds ()
789 {
790- m_first_non_ws = cpp_byte_column_to_display_column (line.get_buffer (),
791- line.length (),
792- m_first_non_ws);
793-
794- m_last_non_ws = cpp_byte_column_to_display_column (line.get_buffer (),
795- line.length (),
796- m_last_non_ws);
797+ m_first_non_ws_disp_col = INT_MAX;
798+ m_last_non_ws_disp_col = 0;
799 }
800 };
801
802@@ -351,8 +348,8 @@ class layout
803 private:
804 bool will_show_line_p (linenum_type row) const;
805 void print_leading_fixits (linenum_type row);
806- void print_source_line (linenum_type row, const char *line, int line_bytes,
807- line_bounds *lbounds_out);
808+ line_bounds print_source_line (linenum_type row, const char *line,
809+ int line_bytes);
810 bool should_print_annotation_line_p (linenum_type row) const;
811 void start_annotation_line (char margin_char = ' ') const;
812 void print_annotation_line (linenum_type row, const line_bounds lbounds);
813@@ -513,16 +510,16 @@ colorizer::get_color_by_name (const char
814 Initialize various layout_point fields from expanded_location
815 equivalents; we've already filtered on file. */
816
817-layout_range::layout_range (const expanded_location *start_exploc,
818- const expanded_location *finish_exploc,
819+layout_range::layout_range (const exploc_with_display_col &start_exploc,
820+ const exploc_with_display_col &finish_exploc,
821 enum range_display_kind range_display_kind,
822- const expanded_location *caret_exploc,
823+ const exploc_with_display_col &caret_exploc,
824 unsigned original_idx,
825 const range_label *label)
826-: m_start (*start_exploc),
827- m_finish (*finish_exploc),
828+: m_start (start_exploc),
829+ m_finish (finish_exploc),
830 m_range_display_kind (range_display_kind),
831- m_caret (*caret_exploc),
832+ m_caret (caret_exploc),
833 m_original_idx (original_idx),
834 m_label (label)
835 {
836@@ -646,6 +643,9 @@ layout_range::intersects_line_p (linenum
837
838 #if CHECKING_P
839
840+/* Default for when we don't care what the tab expansion is set to. */
841+static const int def_tabstop = 8;
842+
843 /* Create some expanded locations for testing layout_range. The filename
844 member of the explocs is set to the empty string. This member will only be
845 inspected by the calls to location_compute_display_column() made from the
846@@ -662,8 +662,11 @@ make_range (int start_line, int start_co
847 = {"", start_line, start_col, NULL, false};
848 const expanded_location finish_exploc
849 = {"", end_line, end_col, NULL, false};
850- return layout_range (&start_exploc, &finish_exploc, SHOW_RANGE_WITHOUT_CARET,
851- &start_exploc, 0, NULL);
852+ return layout_range (exploc_with_display_col (start_exploc, def_tabstop),
853+ exploc_with_display_col (finish_exploc, def_tabstop),
854+ SHOW_RANGE_WITHOUT_CARET,
855+ exploc_with_display_col (start_exploc, def_tabstop),
856+ 0, NULL);
857 }
858
859 /* Selftests for layout_range::contains_point and
860@@ -964,7 +967,7 @@ layout::layout (diagnostic_context * con
861 : m_context (context),
862 m_pp (context->printer),
863 m_primary_loc (richloc->get_range (0)->m_loc),
864- m_exploc (richloc->get_expanded_location (0)),
865+ m_exploc (richloc->get_expanded_location (0), context->tabstop),
866 m_colorizer (context, diagnostic_kind),
867 m_colorize_source_p (context->colorize_source_p),
868 m_show_labels_p (context->show_labels_p),
869@@ -1060,7 +1063,10 @@ layout::maybe_add_location_range (const
870
871 /* Everything is now known to be in the correct source file,
872 but it may require further sanitization. */
873- layout_range ri (&start, &finish, loc_range->m_range_display_kind, &caret,
874+ layout_range ri (exploc_with_display_col (start, m_context->tabstop),
875+ exploc_with_display_col (finish, m_context->tabstop),
876+ loc_range->m_range_display_kind,
877+ exploc_with_display_col (caret, m_context->tabstop),
878 original_idx, loc_range->m_label);
879
880 /* If we have a range that finishes before it starts (perhaps
881@@ -1394,7 +1400,7 @@ layout::calculate_x_offset_display ()
882 = get_line_bytes_without_trailing_whitespace (line.get_buffer (),
883 line.length ());
884 int eol_display_column
885- = cpp_display_width (line.get_buffer (), line_bytes);
886+ = cpp_display_width (line.get_buffer (), line_bytes, m_context->tabstop);
887 if (caret_display_column > eol_display_column
888 || !caret_display_column)
889 {
890@@ -1445,16 +1451,13 @@ layout::calculate_x_offset_display ()
891 }
892
893 /* Print line ROW of source code, potentially colorized at any ranges, and
894- populate *LBOUNDS_OUT.
895- LINE is the source line (not necessarily 0-terminated) and LINE_BYTES
896- is its length in bytes.
897- This function deals only with byte offsets, not display columns, so
898- m_x_offset_display must be converted from display to byte units. In
899- particular, LINE_BYTES and LBOUNDS_OUT are in bytes. */
900+ return the line bounds. LINE is the source line (not necessarily
901+ 0-terminated) and LINE_BYTES is its length in bytes. In order to handle both
902+ colorization and tab expansion, this function tracks the line position in
903+ both byte and display column units. */
904
905-void
906-layout::print_source_line (linenum_type row, const char *line, int line_bytes,
907- line_bounds *lbounds_out)
908+line_bounds
909+layout::print_source_line (linenum_type row, const char *line, int line_bytes)
910 {
911 m_colorizer.set_normal_text ();
912
913@@ -1469,30 +1472,29 @@ layout::print_source_line (linenum_type
914 else
915 pp_space (m_pp);
916
917- /* We will stop printing the source line at any trailing whitespace, and start
918- printing it as per m_x_offset_display. */
919+ /* We will stop printing the source line at any trailing whitespace. */
920 line_bytes = get_line_bytes_without_trailing_whitespace (line,
921 line_bytes);
922- int x_offset_bytes = 0;
923- if (m_x_offset_display)
924- {
925- x_offset_bytes = cpp_display_column_to_byte_column (line, line_bytes,
926- m_x_offset_display);
927- /* In case the leading portion of the line that will be skipped over ends
928- with a character with wcwidth > 1, then it is possible we skipped too
929- much, so account for that by padding with spaces. */
930- const int overage
931- = cpp_byte_column_to_display_column (line, line_bytes, x_offset_bytes)
932- - m_x_offset_display;
933- for (int column = 0; column < overage; ++column)
934- pp_space (m_pp);
935- line += x_offset_bytes;
936- }
937
938- /* Print the line. */
939- int first_non_ws = INT_MAX;
940- int last_non_ws = 0;
941- for (int col_byte = 1 + x_offset_bytes; col_byte <= line_bytes; col_byte++)
942+ /* This object helps to keep track of which display column we are at, which is
943+ necessary for computing the line bounds in display units, for doing
944+ tab expansion, and for implementing m_x_offset_display. */
945+ cpp_display_width_computation dw (line, line_bytes, m_context->tabstop);
946+
947+ /* Skip the first m_x_offset_display display columns. In case the leading
948+ portion that will be skipped ends with a character with wcwidth > 1, then
949+ it is possible we skipped too much, so account for that by padding with
950+ spaces. Note that this does the right thing too in case a tab was the last
951+ character to be skipped over; the tab is effectively replaced by the
952+ correct number of trailing spaces needed to offset by the desired number of
953+ display columns. */
954+ for (int skipped_display_cols = dw.advance_display_cols (m_x_offset_display);
955+ skipped_display_cols > m_x_offset_display; --skipped_display_cols)
956+ pp_space (m_pp);
957+
958+ /* Print the line and compute the line_bounds. */
959+ line_bounds lbounds;
960+ while (!dw.done ())
961 {
962 /* Assuming colorization is enabled for the caret and underline
963 characters, we may also colorize the associated characters
964@@ -1510,7 +1512,8 @@ layout::print_source_line (linenum_type
965 {
966 bool in_range_p;
967 point_state state;
968- in_range_p = get_state_at_point (row, col_byte,
969+ const int start_byte_col = dw.bytes_processed () + 1;
970+ in_range_p = get_state_at_point (row, start_byte_col,
971 0, INT_MAX,
972 CU_BYTES,
973 &state);
974@@ -1519,22 +1522,44 @@ layout::print_source_line (linenum_type
975 else
976 m_colorizer.set_normal_text ();
977 }
978- char c = *line;
979- if (c == '\0' || c == '\t' || c == '\r')
980- c = ' ';
981- if (c != ' ')
982+
983+ /* Get the display width of the next character to be output, expanding
984+ tabs and replacing some control bytes with spaces as necessary. */
985+ const char *c = dw.next_byte ();
986+ const int start_disp_col = dw.display_cols_processed () + 1;
987+ const int this_display_width = dw.process_next_codepoint ();
988+ if (*c == '\t')
989+ {
990+ /* The returned display width is the number of spaces into which the
991+ tab should be expanded. */
992+ for (int i = 0; i != this_display_width; ++i)
993+ pp_space (m_pp);
994+ continue;
995+ }
996+ if (*c == '\0' || *c == '\r')
997 {
998- last_non_ws = col_byte;
999- if (first_non_ws == INT_MAX)
1000- first_non_ws = col_byte;
1001+ /* cpp_wcwidth() promises to return 1 for all control bytes, and we
1002+ want to output these as a single space too, so this case is
1003+ actually the same as the '\t' case. */
1004+ gcc_assert (this_display_width == 1);
1005+ pp_space (m_pp);
1006+ continue;
1007 }
1008- pp_character (m_pp, c);
1009- line++;
1010+
1011+ /* We have a (possibly multibyte) character to output; update the line
1012+ bounds if it is not whitespace. */
1013+ if (*c != ' ')
1014+ {
1015+ lbounds.m_last_non_ws_disp_col = dw.display_cols_processed ();
1016+ if (lbounds.m_first_non_ws_disp_col == INT_MAX)
1017+ lbounds.m_first_non_ws_disp_col = start_disp_col;
1018+ }
1019+
1020+ /* Output the character. */
1021+ while (c != dw.next_byte ()) pp_character (m_pp, *c++);
1022 }
1023 print_newline ();
1024-
1025- lbounds_out->m_first_non_ws = first_non_ws;
1026- lbounds_out->m_last_non_ws = last_non_ws;
1027+ return lbounds;
1028 }
1029
1030 /* Determine if we should print an annotation line for ROW.
1031@@ -1576,14 +1601,13 @@ layout::start_annotation_line (char marg
1032 }
1033
1034 /* Print a line consisting of the caret/underlines for the given
1035- source line. This function works with display columns, rather than byte
1036- counts; in particular, LBOUNDS should be in display column units. */
1037+ source line. */
1038
1039 void
1040 layout::print_annotation_line (linenum_type row, const line_bounds lbounds)
1041 {
1042 int x_bound = get_x_bound_for_row (row, m_exploc.m_display_col,
1043- lbounds.m_last_non_ws);
1044+ lbounds.m_last_non_ws_disp_col);
1045
1046 start_annotation_line ();
1047 pp_space (m_pp);
1048@@ -1593,8 +1617,8 @@ layout::print_annotation_line (linenum_t
1049 bool in_range_p;
1050 point_state state;
1051 in_range_p = get_state_at_point (row, column,
1052- lbounds.m_first_non_ws,
1053- lbounds.m_last_non_ws,
1054+ lbounds.m_first_non_ws_disp_col,
1055+ lbounds.m_last_non_ws_disp_col,
1056 CU_DISPLAY_COLS,
1057 &state);
1058 if (in_range_p)
1059@@ -1631,12 +1655,14 @@ layout::print_annotation_line (linenum_t
1060 class line_label
1061 {
1062 public:
1063- line_label (int state_idx, int column, label_text text)
1064+ line_label (diagnostic_context *context, int state_idx, int column,
1065+ label_text text)
1066 : m_state_idx (state_idx), m_column (column),
1067 m_text (text), m_label_line (0), m_has_vbar (true)
1068 {
1069 const int bytes = strlen (text.m_buffer);
1070- m_display_width = cpp_display_width (text.m_buffer, bytes);
1071+ m_display_width
1072+ = cpp_display_width (text.m_buffer, bytes, context->tabstop);
1073 }
1074
1075 /* Sorting is primarily by column, then by state index. */
1076@@ -1696,7 +1722,7 @@ layout::print_any_labels (linenum_type r
1077 if (text.m_buffer == NULL)
1078 continue;
1079
1080- labels.safe_push (line_label (i, disp_col, text));
1081+ labels.safe_push (line_label (m_context, i, disp_col, text));
1082 }
1083 }
1084
1085@@ -1976,7 +2002,8 @@ public:
1086
1087 /* Get the range of bytes or display columns that HINT would affect. */
1088 static column_range
1089-get_affected_range (const fixit_hint *hint, enum column_unit col_unit)
1090+get_affected_range (diagnostic_context *context,
1091+ const fixit_hint *hint, enum column_unit col_unit)
1092 {
1093 expanded_location exploc_start = expand_location (hint->get_start_loc ());
1094 expanded_location exploc_finish = expand_location (hint->get_next_loc ());
1095@@ -1986,11 +2013,13 @@ get_affected_range (const fixit_hint *hi
1096 int finish_column;
1097 if (col_unit == CU_DISPLAY_COLS)
1098 {
1099- start_column = location_compute_display_column (exploc_start);
1100+ start_column
1101+ = location_compute_display_column (exploc_start, context->tabstop);
1102 if (hint->insertion_p ())
1103 finish_column = start_column - 1;
1104 else
1105- finish_column = location_compute_display_column (exploc_finish);
1106+ finish_column
1107+ = location_compute_display_column (exploc_finish, context->tabstop);
1108 }
1109 else
1110 {
1111@@ -2003,12 +2032,12 @@ get_affected_range (const fixit_hint *hi
1112 /* Get the range of display columns that would be printed for HINT. */
1113
1114 static column_range
1115-get_printed_columns (const fixit_hint *hint)
1116+get_printed_columns (diagnostic_context *context, const fixit_hint *hint)
1117 {
1118 expanded_location exploc = expand_location (hint->get_start_loc ());
1119- int start_column = location_compute_display_column (exploc);
1120- int hint_width = cpp_display_width (hint->get_string (),
1121- hint->get_length ());
1122+ int start_column = location_compute_display_column (exploc, context->tabstop);
1123+ int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
1124+ context->tabstop);
1125 int final_hint_column = start_column + hint_width - 1;
1126 if (hint->insertion_p ())
1127 {
1128@@ -2018,7 +2047,8 @@ get_printed_columns (const fixit_hint *h
1129 {
1130 exploc = expand_location (hint->get_next_loc ());
1131 --exploc.column;
1132- int finish_column = location_compute_display_column (exploc);
1133+ int finish_column
1134+ = location_compute_display_column (exploc, context->tabstop);
1135 return column_range (start_column,
1136 MAX (finish_column, final_hint_column));
1137 }
1138@@ -2035,12 +2065,14 @@ public:
1139 correction (column_range affected_bytes,
1140 column_range affected_columns,
1141 column_range printed_columns,
1142- const char *new_text, size_t new_text_len)
1143+ const char *new_text, size_t new_text_len,
1144+ int tabstop)
1145 : m_affected_bytes (affected_bytes),
1146 m_affected_columns (affected_columns),
1147 m_printed_columns (printed_columns),
1148 m_text (xstrdup (new_text)),
1149 m_byte_length (new_text_len),
1150+ m_tabstop (tabstop),
1151 m_alloc_sz (new_text_len + 1)
1152 {
1153 compute_display_cols ();
1154@@ -2058,7 +2090,7 @@ public:
1155
1156 void compute_display_cols ()
1157 {
1158- m_display_cols = cpp_display_width (m_text, m_byte_length);
1159+ m_display_cols = cpp_display_width (m_text, m_byte_length, m_tabstop);
1160 }
1161
1162 void overwrite (int dst_offset, const char_span &src_span)
1163@@ -2086,6 +2118,7 @@ public:
1164 char *m_text;
1165 size_t m_byte_length; /* Not including null-terminator. */
1166 int m_display_cols;
1167+ int m_tabstop;
1168 size_t m_alloc_sz;
1169 };
1170
1171@@ -2121,13 +2154,15 @@ correction::ensure_terminated ()
1172 class line_corrections
1173 {
1174 public:
1175- line_corrections (const char *filename, linenum_type row)
1176- : m_filename (filename), m_row (row)
1177+ line_corrections (diagnostic_context *context, const char *filename,
1178+ linenum_type row)
1179+ : m_context (context), m_filename (filename), m_row (row)
1180 {}
1181 ~line_corrections ();
1182
1183 void add_hint (const fixit_hint *hint);
1184
1185+ diagnostic_context *m_context;
1186 const char *m_filename;
1187 linenum_type m_row;
1188 auto_vec <correction *> m_corrections;
1189@@ -2173,9 +2208,10 @@ source_line::source_line (const char *fi
1190 void
1191 line_corrections::add_hint (const fixit_hint *hint)
1192 {
1193- column_range affected_bytes = get_affected_range (hint, CU_BYTES);
1194- column_range affected_columns = get_affected_range (hint, CU_DISPLAY_COLS);
1195- column_range printed_columns = get_printed_columns (hint);
1196+ column_range affected_bytes = get_affected_range (m_context, hint, CU_BYTES);
1197+ column_range affected_columns = get_affected_range (m_context, hint,
1198+ CU_DISPLAY_COLS);
1199+ column_range printed_columns = get_printed_columns (m_context, hint);
1200
1201 /* Potentially consolidate. */
1202 if (!m_corrections.is_empty ())
1203@@ -2243,7 +2279,8 @@ line_corrections::add_hint (const fixit_
1204 affected_columns,
1205 printed_columns,
1206 hint->get_string (),
1207- hint->get_length ()));
1208+ hint->get_length (),
1209+ m_context->tabstop));
1210 }
1211
1212 /* If there are any fixit hints on source line ROW, print them.
1213@@ -2257,7 +2294,7 @@ layout::print_trailing_fixits (linenum_t
1214 {
1215 /* Build a list of correction instances for the line,
1216 potentially consolidating hints (for the sake of readability). */
1217- line_corrections corrections (m_exploc.file, row);
1218+ line_corrections corrections (m_context, m_exploc.file, row);
1219 for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
1220 {
1221 const fixit_hint *hint = m_fixit_hints[i];
1222@@ -2499,15 +2536,11 @@ layout::print_line (linenum_type row)
1223 if (!line)
1224 return;
1225
1226- line_bounds lbounds;
1227 print_leading_fixits (row);
1228- print_source_line (row, line.get_buffer (), line.length (), &lbounds);
1229+ const line_bounds lbounds
1230+ = print_source_line (row, line.get_buffer (), line.length ());
1231 if (should_print_annotation_line_p (row))
1232- {
1233- if (lbounds.m_first_non_ws != INT_MAX)
1234- lbounds.convert_to_display_cols (line);
1235- print_annotation_line (row, lbounds);
1236- }
1237+ print_annotation_line (row, lbounds);
1238 if (m_show_labels_p)
1239 print_any_labels (row);
1240 print_trailing_fixits (row);
1241@@ -2670,9 +2703,11 @@ test_layout_x_offset_display_utf8 (const
1242
1243 char_span lspan = location_get_source_line (tmp.get_filename (), 1);
1244 ASSERT_EQ (line_display_cols,
1245- cpp_display_width (lspan.get_buffer (), lspan.length ()));
1246+ cpp_display_width (lspan.get_buffer (), lspan.length (),
1247+ def_tabstop));
1248 ASSERT_EQ (line_display_cols,
1249- location_compute_display_column (expand_location (line_end)));
1250+ location_compute_display_column (expand_location (line_end),
1251+ def_tabstop));
1252 ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
1253 "\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
1254
1255@@ -2774,6 +2809,111 @@ test_layout_x_offset_display_utf8 (const
1256
1257 }
1258
1259+static void
1260+test_layout_x_offset_display_tab (const line_table_case &case_)
1261+{
1262+ const char *content
1263+ = "This line is very long, so that we can use it to test the logic for "
1264+ "clipping long lines. Also this: `\t' is a tab that occupies 1 byte and "
1265+ "a variable number of display columns, starting at column #103.\n";
1266+
1267+ /* Number of bytes in the line, subtracting one to remove the newline. */
1268+ const int line_bytes = strlen (content) - 1;
1269+
1270+ /* The column where the tab begins. Byte or display is the same as there are
1271+ no multibyte characters earlier on the line. */
1272+ const int tab_col = 103;
1273+
1274+ /* Effective extra size of the tab beyond what a single space would have taken
1275+ up, indexed by tabstop. */
1276+ static const int num_tabstops = 11;
1277+ int extra_width[num_tabstops];
1278+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
1279+ {
1280+ const int this_tab_size = tabstop - (tab_col - 1) % tabstop;
1281+ extra_width[tabstop] = this_tab_size - 1;
1282+ }
1283+ /* Example of this calculation: if tabstop is 10, the tab starting at column
1284+ #103 has to expand into 8 spaces, covering columns 103-110, so that the
1285+ next character is at column #111. So it takes up 7 more columns than
1286+ a space would have taken up. */
1287+ ASSERT_EQ (7, extra_width[10]);
1288+
1289+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
1290+ line_table_test ltt (case_);
1291+
1292+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
1293+
1294+ location_t line_end = linemap_position_for_column (line_table, line_bytes);
1295+
1296+ /* Don't attempt to run the tests if column data might be unavailable. */
1297+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
1298+ return;
1299+
1300+ /* Check that cpp_display_width handles the tabs as expected. */
1301+ char_span lspan = location_get_source_line (tmp.get_filename (), 1);
1302+ ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
1303+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
1304+ {
1305+ ASSERT_EQ (line_bytes + extra_width[tabstop],
1306+ cpp_display_width (lspan.get_buffer (), lspan.length (),
1307+ tabstop));
1308+ ASSERT_EQ (line_bytes + extra_width[tabstop],
1309+ location_compute_display_column (expand_location (line_end),
1310+ tabstop));
1311+ }
1312+
1313+ /* Check that the tab is expanded to the expected number of spaces. */
1314+ rich_location richloc (line_table,
1315+ linemap_position_for_column (line_table,
1316+ tab_col + 1));
1317+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
1318+ {
1319+ test_diagnostic_context dc;
1320+ dc.tabstop = tabstop;
1321+ layout test_layout (&dc, &richloc, DK_ERROR);
1322+ test_layout.print_line (1);
1323+ const char *out = pp_formatted_text (dc.printer);
1324+ ASSERT_EQ (NULL, strchr (out, '\t'));
1325+ const char *left_quote = strchr (out, '`');
1326+ const char *right_quote = strchr (out, '\'');
1327+ ASSERT_NE (NULL, left_quote);
1328+ ASSERT_NE (NULL, right_quote);
1329+ ASSERT_EQ (right_quote - left_quote, extra_width[tabstop] + 2);
1330+ }
1331+
1332+ /* Check that the line is offset properly and that the tab is broken up
1333+ into the expected number of spaces when it is the last character skipped
1334+ over. */
1335+ for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
1336+ {
1337+ test_diagnostic_context dc;
1338+ dc.tabstop = tabstop;
1339+ static const int small_width = 24;
1340+ dc.caret_max_width = small_width - 4;
1341+ dc.min_margin_width = test_left_margin - test_linenum_sep + 1;
1342+ dc.show_line_numbers_p = true;
1343+ layout test_layout (&dc, &richloc, DK_ERROR);
1344+ test_layout.print_line (1);
1345+
1346+ /* We have arranged things so that two columns will be printed before
1347+ the caret. If the tab results in more than one space, this should
1348+ produce two spaces in the output; otherwise, it will be a single space
1349+ preceded by the opening quote before the tab character. */
1350+ const char *output1
1351+ = " 1 | ' is a tab that occupies 1 byte and a variable number of "
1352+ "display columns, starting at column #103.\n"
1353+ " | ^\n\n";
1354+ const char *output2
1355+ = " 1 | ` ' is a tab that occupies 1 byte and a variable number of "
1356+ "display columns, starting at column #103.\n"
1357+ " | ^\n\n";
1358+ const char *expected_output = (extra_width[tabstop] ? output1 : output2);
1359+ ASSERT_STREQ (expected_output, pp_formatted_text (dc.printer));
1360+ }
1361+}
1362+
1363+
1364 /* Verify that diagnostic_show_locus works sanely on UNKNOWN_LOCATION. */
1365
1366 static void
1367@@ -3854,6 +3994,27 @@ test_one_liner_labels_utf8 ()
1368 }
1369 }
1370
1371+/* Make sure that colorization codes don't interrupt a multibyte
1372+ sequence, which would corrupt it. */
1373+static void
1374+test_one_liner_colorized_utf8 ()
1375+{
1376+ test_diagnostic_context dc;
1377+ dc.colorize_source_p = true;
1378+ diagnostic_color_init (&dc, DIAGNOSTICS_COLOR_YES);
1379+ const location_t pi = linemap_position_for_column (line_table, 12);
1380+ rich_location richloc (line_table, pi);
1381+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1382+
1383+ /* In order to avoid having the test depend on exactly how the colorization
1384+ was effected, just confirm there are two pi characters in the output. */
1385+ const char *result = pp_formatted_text (dc.printer);
1386+ const char *null_term = result + strlen (result);
1387+ const char *first_pi = strstr (result, "\xcf\x80");
1388+ ASSERT_TRUE (first_pi && first_pi <= null_term - 2);
1389+ ASSERT_STR_CONTAINS (first_pi + 2, "\xcf\x80");
1390+}
1391+
1392 /* Run the various one-liner tests. */
1393
1394 static void
1395@@ -3884,8 +4045,10 @@ test_diagnostic_show_locus_one_liner_utf
1396 ASSERT_EQ (31, LOCATION_COLUMN (line_end));
1397
1398 char_span lspan = location_get_source_line (tmp.get_filename (), 1);
1399- ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length ()));
1400- ASSERT_EQ (25, location_compute_display_column (expand_location (line_end)));
1401+ ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
1402+ def_tabstop));
1403+ ASSERT_EQ (25, location_compute_display_column (expand_location (line_end),
1404+ def_tabstop));
1405
1406 test_one_liner_simple_caret_utf8 ();
1407 test_one_liner_caret_and_range_utf8 ();
1408@@ -3900,6 +4063,7 @@ test_diagnostic_show_locus_one_liner_utf
1409 test_one_liner_many_fixits_1_utf8 ();
1410 test_one_liner_many_fixits_2_utf8 ();
1411 test_one_liner_labels_utf8 ();
1412+ test_one_liner_colorized_utf8 ();
1413 }
1414
1415 /* Verify that gcc_rich_location::add_location_if_nearby works. */
1416@@ -4272,25 +4436,28 @@ test_overlapped_fixit_printing (const li
1417 /* Unit-test the line_corrections machinery. */
1418 ASSERT_EQ (3, richloc.get_num_fixit_hints ());
1419 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1420- ASSERT_EQ (column_range (12, 12), get_affected_range (hint_0, CU_BYTES));
1421 ASSERT_EQ (column_range (12, 12),
1422- get_affected_range (hint_0, CU_DISPLAY_COLS));
1423- ASSERT_EQ (column_range (12, 22), get_printed_columns (hint_0));
1424+ get_affected_range (&dc, hint_0, CU_BYTES));
1425+ ASSERT_EQ (column_range (12, 12),
1426+ get_affected_range (&dc, hint_0, CU_DISPLAY_COLS));
1427+ ASSERT_EQ (column_range (12, 22), get_printed_columns (&dc, hint_0));
1428 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1429- ASSERT_EQ (column_range (18, 18), get_affected_range (hint_1, CU_BYTES));
1430 ASSERT_EQ (column_range (18, 18),
1431- get_affected_range (hint_1, CU_DISPLAY_COLS));
1432- ASSERT_EQ (column_range (18, 20), get_printed_columns (hint_1));
1433+ get_affected_range (&dc, hint_1, CU_BYTES));
1434+ ASSERT_EQ (column_range (18, 18),
1435+ get_affected_range (&dc, hint_1, CU_DISPLAY_COLS));
1436+ ASSERT_EQ (column_range (18, 20), get_printed_columns (&dc, hint_1));
1437 const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
1438- ASSERT_EQ (column_range (29, 28), get_affected_range (hint_2, CU_BYTES));
1439 ASSERT_EQ (column_range (29, 28),
1440- get_affected_range (hint_2, CU_DISPLAY_COLS));
1441- ASSERT_EQ (column_range (29, 29), get_printed_columns (hint_2));
1442+ get_affected_range (&dc, hint_2, CU_BYTES));
1443+ ASSERT_EQ (column_range (29, 28),
1444+ get_affected_range (&dc, hint_2, CU_DISPLAY_COLS));
1445+ ASSERT_EQ (column_range (29, 29), get_printed_columns (&dc, hint_2));
1446
1447 /* Add each hint in turn to a line_corrections instance,
1448 and verify that they are consolidated into one correction instance
1449 as expected. */
1450- line_corrections lc (tmp.get_filename (), 1);
1451+ line_corrections lc (&dc, tmp.get_filename (), 1);
1452
1453 /* The first replace hint by itself. */
1454 lc.add_hint (hint_0);
1455@@ -4484,25 +4651,28 @@ test_overlapped_fixit_printing_utf8 (con
1456 /* Unit-test the line_corrections machinery. */
1457 ASSERT_EQ (3, richloc.get_num_fixit_hints ());
1458 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1459- ASSERT_EQ (column_range (14, 14), get_affected_range (hint_0, CU_BYTES));
1460+ ASSERT_EQ (column_range (14, 14),
1461+ get_affected_range (&dc, hint_0, CU_BYTES));
1462 ASSERT_EQ (column_range (12, 12),
1463- get_affected_range (hint_0, CU_DISPLAY_COLS));
1464- ASSERT_EQ (column_range (12, 22), get_printed_columns (hint_0));
1465+ get_affected_range (&dc, hint_0, CU_DISPLAY_COLS));
1466+ ASSERT_EQ (column_range (12, 22), get_printed_columns (&dc, hint_0));
1467 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1468- ASSERT_EQ (column_range (22, 22), get_affected_range (hint_1, CU_BYTES));
1469+ ASSERT_EQ (column_range (22, 22),
1470+ get_affected_range (&dc, hint_1, CU_BYTES));
1471 ASSERT_EQ (column_range (18, 18),
1472- get_affected_range (hint_1, CU_DISPLAY_COLS));
1473- ASSERT_EQ (column_range (18, 20), get_printed_columns (hint_1));
1474+ get_affected_range (&dc, hint_1, CU_DISPLAY_COLS));
1475+ ASSERT_EQ (column_range (18, 20), get_printed_columns (&dc, hint_1));
1476 const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
1477- ASSERT_EQ (column_range (35, 34), get_affected_range (hint_2, CU_BYTES));
1478+ ASSERT_EQ (column_range (35, 34),
1479+ get_affected_range (&dc, hint_2, CU_BYTES));
1480 ASSERT_EQ (column_range (30, 29),
1481- get_affected_range (hint_2, CU_DISPLAY_COLS));
1482- ASSERT_EQ (column_range (30, 30), get_printed_columns (hint_2));
1483+ get_affected_range (&dc, hint_2, CU_DISPLAY_COLS));
1484+ ASSERT_EQ (column_range (30, 30), get_printed_columns (&dc, hint_2));
1485
1486 /* Add each hint in turn to a line_corrections instance,
1487 and verify that they are consolidated into one correction instance
1488 as expected. */
1489- line_corrections lc (tmp.get_filename (), 1);
1490+ line_corrections lc (&dc, tmp.get_filename (), 1);
1491
1492 /* The first replace hint by itself. */
1493 lc.add_hint (hint_0);
1494@@ -4689,6 +4859,8 @@ test_overlapped_fixit_printing_2 (const
1495
1496 /* Two insertions, in the wrong order. */
1497 {
1498+ test_diagnostic_context dc;
1499+
1500 rich_location richloc (line_table, col_20);
1501 richloc.add_fixit_insert_before (col_23, "{");
1502 richloc.add_fixit_insert_before (col_21, "}");
1503@@ -4696,14 +4868,15 @@ test_overlapped_fixit_printing_2 (const
1504 /* These fixits should be accepted; they can't be consolidated. */
1505 ASSERT_EQ (2, richloc.get_num_fixit_hints ());
1506 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1507- ASSERT_EQ (column_range (23, 22), get_affected_range (hint_0, CU_BYTES));
1508- ASSERT_EQ (column_range (23, 23), get_printed_columns (hint_0));
1509+ ASSERT_EQ (column_range (23, 22),
1510+ get_affected_range (&dc, hint_0, CU_BYTES));
1511+ ASSERT_EQ (column_range (23, 23), get_printed_columns (&dc, hint_0));
1512 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1513- ASSERT_EQ (column_range (21, 20), get_affected_range (hint_1, CU_BYTES));
1514- ASSERT_EQ (column_range (21, 21), get_printed_columns (hint_1));
1515+ ASSERT_EQ (column_range (21, 20),
1516+ get_affected_range (&dc, hint_1, CU_BYTES));
1517+ ASSERT_EQ (column_range (21, 21), get_printed_columns (&dc, hint_1));
1518
1519 /* Verify that they're printed correctly. */
1520- test_diagnostic_context dc;
1521 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1522 ASSERT_STREQ (" int a5[][0][0] = { 1, 2 };\n"
1523 " ^\n"
1524@@ -4955,6 +5128,65 @@ test_fixit_deletion_affecting_newline (c
1525 pp_formatted_text (dc.printer));
1526 }
1527
1528+static void
1529+test_tab_expansion (const line_table_case &case_)
1530+{
1531+ /* Create a tempfile and write some text to it. This example uses a tabstop
1532+ of 8, as the column numbers attempt to indicate:
1533+
1534+ .....................000.01111111111.22222333333 display
1535+ .....................123.90123456789.56789012345 columns */
1536+ const char *content = " \t This: `\t' is a tab.\n";
1537+ /* ....................000 00000011111 11111222222 byte
1538+ ....................123 45678901234 56789012345 columns */
1539+
1540+ const int tabstop = 8;
1541+ const int first_non_ws_byte_col = 7;
1542+ const int right_quote_byte_col = 15;
1543+ const int last_byte_col = 25;
1544+ ASSERT_EQ (35, cpp_display_width (content, last_byte_col, tabstop));
1545+
1546+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
1547+ line_table_test ltt (case_);
1548+ linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
1549+
1550+ /* Don't attempt to run the tests if column data might be unavailable. */
1551+ location_t line_end = linemap_position_for_column (line_table, last_byte_col);
1552+ if (line_end > LINE_MAP_MAX_LOCATION_WITH_COLS)
1553+ return;
1554+
1555+ /* Check that the leading whitespace with mixed tabs and spaces is expanded
1556+ into 11 spaces. Recall that print_line() also puts one space before
1557+ everything too. */
1558+ {
1559+ test_diagnostic_context dc;
1560+ dc.tabstop = tabstop;
1561+ rich_location richloc (line_table,
1562+ linemap_position_for_column (line_table,
1563+ first_non_ws_byte_col));
1564+ layout test_layout (&dc, &richloc, DK_ERROR);
1565+ test_layout.print_line (1);
1566+ ASSERT_STREQ (" This: ` ' is a tab.\n"
1567+ " ^\n",
1568+ pp_formatted_text (dc.printer));
1569+ }
1570+
1571+ /* Confirm the display width was tracked correctly across the internal tab
1572+ as well. */
1573+ {
1574+ test_diagnostic_context dc;
1575+ dc.tabstop = tabstop;
1576+ rich_location richloc (line_table,
1577+ linemap_position_for_column (line_table,
1578+ right_quote_byte_col));
1579+ layout test_layout (&dc, &richloc, DK_ERROR);
1580+ test_layout.print_line (1);
1581+ ASSERT_STREQ (" This: ` ' is a tab.\n"
1582+ " ^\n",
1583+ pp_formatted_text (dc.printer));
1584+ }
1585+}
1586+
1587 /* Verify that line numbers are correctly printed for the case of
1588 a multiline range in which the width of the line numbers changes
1589 (e.g. from "9" to "10"). */
1590@@ -5012,6 +5244,7 @@ diagnostic_show_locus_c_tests ()
1591 test_layout_range_for_multiple_lines ();
1592
1593 for_each_line_table_case (test_layout_x_offset_display_utf8);
1594+ for_each_line_table_case (test_layout_x_offset_display_tab);
1595
1596 test_get_line_bytes_without_trailing_whitespace ();
1597
1598@@ -5029,6 +5262,7 @@ diagnostic_show_locus_c_tests ()
1599 for_each_line_table_case (test_fixit_insert_containing_newline_2);
1600 for_each_line_table_case (test_fixit_replace_containing_newline);
1601 for_each_line_table_case (test_fixit_deletion_affecting_newline);
1602+ for_each_line_table_case (test_tab_expansion);
1603
1604 test_line_numbers_multiline_range ();
1605 }
1606diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
1607--- a/gcc/doc/invoke.texi 2021-12-24 20:23:46.876739587 -0800
1608+++ b/gcc/doc/invoke.texi 2021-12-25 01:20:53.487636494 -0800
1609@@ -293,7 +293,9 @@ Objective-C and Objective-C++ Dialects}.
1610 -fdiagnostics-show-template-tree -fno-elide-type @gol
1611 -fdiagnostics-path-format=@r{[}none@r{|}separate-events@r{|}inline-events@r{]} @gol
1612 -fdiagnostics-show-path-depths @gol
1613--fno-show-column}
1614+-fno-show-column @gol
1615+-fdiagnostics-column-unit=@r{[}display@r{|}byte@r{]} @gol
1616+-fdiagnostics-column-origin=@var{origin}}
1617
1618 @item Warning Options
1619 @xref{Warning Options,,Options to Request or Suppress Warnings}.
1620@@ -4424,6 +4426,31 @@ Do not print column numbers in diagnosti
1621 diagnostics are being scanned by a program that does not understand the
1622 column numbers, such as @command{dejagnu}.
1623
1624+@item -fdiagnostics-column-unit=@var{UNIT}
1625+@opindex fdiagnostics-column-unit
1626+Select the units for the column number. This affects traditional diagnostics
1627+(in the absence of @option{-fno-show-column}), as well as JSON format
1628+diagnostics if requested.
1629+
1630+The default @var{UNIT}, @samp{display}, considers the number of display
1631+columns occupied by each character. This may be larger than the number
1632+of bytes required to encode the character, in the case of tab
1633+characters, or it may be smaller, in the case of multibyte characters.
1634+For example, the character ``GREEK SMALL LETTER PI (U+03C0)'' occupies one
1635+display column, and its UTF-8 encoding requires two bytes; the character
1636+``SLIGHTLY SMILING FACE (U+1F642)'' occupies two display columns, and
1637+its UTF-8 encoding requires four bytes.
1638+
1639+Setting @var{UNIT} to @samp{byte} changes the column number to the raw byte
1640+count in all cases, as was traditionally output by GCC prior to version 11.1.0.
1641+
1642+@item -fdiagnostics-column-origin=@var{ORIGIN}
1643+@opindex fdiagnostics-column-origin
1644+Select the origin for column numbers, i.e. the column number assigned to the
1645+first column. The default value of 1 corresponds to traditional GCC
1646+behavior and to the GNU style guide. Some utilities may perform better with an
1647+origin of 0; any non-negative value may be specified.
1648+
1649 @item -fdiagnostics-format=@var{FORMAT}
1650 @opindex fdiagnostics-format
1651 Select a different format for printing diagnostics.
1652@@ -4459,11 +4486,15 @@ might be printed in JSON form (after for
1653 "locations": [
1654 @{
1655 "caret": @{
1656+ "display-column": 3,
1657+ "byte-column": 3,
1658 "column": 3,
1659 "file": "misleading-indentation.c",
1660 "line": 15
1661 @},
1662 "finish": @{
1663+ "display-column": 4,
1664+ "byte-column": 4,
1665 "column": 4,
1666 "file": "misleading-indentation.c",
1667 "line": 15
1668@@ -4479,6 +4510,8 @@ might be printed in JSON form (after for
1669 "locations": [
1670 @{
1671 "caret": @{
1672+ "display-column": 5,
1673+ "byte-column": 5,
1674 "column": 5,
1675 "file": "misleading-indentation.c",
1676 "line": 17
1677@@ -4488,6 +4521,7 @@ might be printed in JSON form (after for
1678 "message": "...this statement, but the latter is @dots{}"
1679 @}
1680 ]
1681+ "column-origin": 1,
1682 @},
1683 @dots{}
1684 ]
1685@@ -4500,10 +4534,34 @@ A diagnostic has a @code{kind}. If this
1686 an @code{option} key describing the command-line option controlling the
1687 warning.
1688
1689-A diagnostic can contain zero or more locations. Each location has up
1690-to three positions within it: a @code{caret} position and optional
1691-@code{start} and @code{finish} positions. A location can also have
1692-an optional @code{label} string. For example, this error:
1693+A diagnostic can contain zero or more locations. Each location has an
1694+optional @code{label} string and up to three positions within it: a
1695+@code{caret} position and optional @code{start} and @code{finish} positions.
1696+A position is described by a @code{file} name, a @code{line} number, and
1697+three numbers indicating a column position:
1698+@itemize @bullet
1699+
1700+@item
1701+@code{display-column} counts display columns, accounting for tabs and
1702+multibyte characters.
1703+
1704+@item
1705+@code{byte-column} counts raw bytes.
1706+
1707+@item
1708+@code{column} is equal to one of
1709+the previous two, as dictated by the @option{-fdiagnostics-column-unit}
1710+option.
1711+
1712+@end itemize
1713+All three columns are relative to the origin specified by
1714+@option{-fdiagnostics-column-origin}, which is typically equal to 1 but may
1715+be set, for instance, to 0 for compatibility with other utilities that
1716+number columns from 0. The column origin is recorded in the JSON output in
1717+the @code{column-origin} tag. In the remaining examples below, the extra
1718+column number outputs have been omitted for brevity.
1719+
1720+For example, this error:
1721
1722 @smallexample
1723 bad-binary-ops.c:64:23: error: invalid operands to binary + (have 'S' @{aka
1724diff --git a/gcc/input.c b/gcc/input.c
1725--- a/gcc/input.c 2020-07-22 23:35:17.664388078 -0700
1726+++ b/gcc/input.c 2021-12-25 01:20:53.487636494 -0800
1727@@ -913,7 +913,7 @@ make_location (location_t caret, source_
1728 source line in order to calculate the display width. If that cannot be done
1729 for any reason, then returns the byte column as a fallback. */
1730 int
1731-location_compute_display_column (expanded_location exploc)
1732+location_compute_display_column (expanded_location exploc, int tabstop)
1733 {
1734 if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
1735 return exploc.column;
1736@@ -921,7 +921,7 @@ location_compute_display_column (expande
1737 /* If line is NULL, this function returns exploc.column which is the
1738 desired fallback. */
1739 return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
1740- exploc.column);
1741+ exploc.column, tabstop);
1742 }
1743
1744 /* Dump statistics to stderr about the memory usage of the line_table
1745@@ -3608,33 +3608,46 @@ test_line_offset_overflow ()
1746
1747 void test_cpp_utf8 ()
1748 {
1749+ const int def_tabstop = 8;
1750 /* Verify that wcwidth of invalid UTF-8 or control bytes is 1. */
1751 {
1752- int w_bad = cpp_display_width ("\xf0!\x9f!\x98!\x82!", 8);
1753+ int w_bad = cpp_display_width ("\xf0!\x9f!\x98!\x82!", 8, def_tabstop);
1754 ASSERT_EQ (8, w_bad);
1755- int w_ctrl = cpp_display_width ("\r\t\n\v\0\1", 6);
1756- ASSERT_EQ (6, w_ctrl);
1757+ int w_ctrl = cpp_display_width ("\r\n\v\0\1", 5, def_tabstop);
1758+ ASSERT_EQ (5, w_ctrl);
1759 }
1760
1761 /* Verify that wcwidth of valid UTF-8 is as expected. */
1762 {
1763- const int w_pi = cpp_display_width ("\xcf\x80", 2);
1764+ const int w_pi = cpp_display_width ("\xcf\x80", 2, def_tabstop);
1765 ASSERT_EQ (1, w_pi);
1766- const int w_emoji = cpp_display_width ("\xf0\x9f\x98\x82", 4);
1767+ const int w_emoji = cpp_display_width ("\xf0\x9f\x98\x82", 4, def_tabstop);
1768 ASSERT_EQ (2, w_emoji);
1769- const int w_umlaut_precomposed = cpp_display_width ("\xc3\xbf", 2);
1770+ const int w_umlaut_precomposed = cpp_display_width ("\xc3\xbf", 2,
1771+ def_tabstop);
1772 ASSERT_EQ (1, w_umlaut_precomposed);
1773- const int w_umlaut_combining = cpp_display_width ("y\xcc\x88", 3);
1774+ const int w_umlaut_combining = cpp_display_width ("y\xcc\x88", 3,
1775+ def_tabstop);
1776 ASSERT_EQ (1, w_umlaut_combining);
1777- const int w_han = cpp_display_width ("\xe4\xb8\xba", 3);
1778+ const int w_han = cpp_display_width ("\xe4\xb8\xba", 3, def_tabstop);
1779 ASSERT_EQ (2, w_han);
1780- const int w_ascii = cpp_display_width ("GCC", 3);
1781+ const int w_ascii = cpp_display_width ("GCC", 3, def_tabstop);
1782 ASSERT_EQ (3, w_ascii);
1783 const int w_mixed = cpp_display_width ("\xcf\x80 = 3.14 \xf0\x9f\x98\x82"
1784- "\x9f! \xe4\xb8\xba y\xcc\x88", 24);
1785+ "\x9f! \xe4\xb8\xba y\xcc\x88",
1786+ 24, def_tabstop);
1787 ASSERT_EQ (18, w_mixed);
1788 }
1789
1790+ /* Verify that display width properly expands tabs. */
1791+ {
1792+ const char *tstr = "\tabc\td";
1793+ ASSERT_EQ (6, cpp_display_width (tstr, 6, 1));
1794+ ASSERT_EQ (10, cpp_display_width (tstr, 6, 3));
1795+ ASSERT_EQ (17, cpp_display_width (tstr, 6, 8));
1796+ ASSERT_EQ (1, cpp_display_column_to_byte_column (tstr, 6, 7, 8));
1797+ }
1798+
1799 /* Verify that cpp_byte_column_to_display_column can go past the end,
1800 and similar edge cases. */
1801 {
1802@@ -3645,10 +3658,13 @@ void test_cpp_utf8 ()
1803 /* 111122223456
1804 Byte columns. */
1805
1806- ASSERT_EQ (5, cpp_display_width (str, 6));
1807- ASSERT_EQ (105, cpp_byte_column_to_display_column (str, 6, 106));
1808- ASSERT_EQ (10000, cpp_byte_column_to_display_column (NULL, 0, 10000));
1809- ASSERT_EQ (0, cpp_byte_column_to_display_column (NULL, 10000, 0));
1810+ ASSERT_EQ (5, cpp_display_width (str, 6, def_tabstop));
1811+ ASSERT_EQ (105,
1812+ cpp_byte_column_to_display_column (str, 6, 106, def_tabstop));
1813+ ASSERT_EQ (10000,
1814+ cpp_byte_column_to_display_column (NULL, 0, 10000, def_tabstop));
1815+ ASSERT_EQ (0,
1816+ cpp_byte_column_to_display_column (NULL, 10000, 0, def_tabstop));
1817 }
1818
1819 /* Verify that cpp_display_column_to_byte_column can go past the end,
1820@@ -3662,21 +3678,25 @@ void test_cpp_utf8 ()
1821 /* 000000000000000000000000000000000111111
1822 111122223333444456666777788889999012345
1823 Byte columns. */
1824- ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 2));
1825- ASSERT_EQ (15, cpp_display_column_to_byte_column (str, 15, 11));
1826- ASSERT_EQ (115, cpp_display_column_to_byte_column (str, 15, 111));
1827- ASSERT_EQ (10000, cpp_display_column_to_byte_column (NULL, 0, 10000));
1828- ASSERT_EQ (0, cpp_display_column_to_byte_column (NULL, 10000, 0));
1829+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 2, def_tabstop));
1830+ ASSERT_EQ (15,
1831+ cpp_display_column_to_byte_column (str, 15, 11, def_tabstop));
1832+ ASSERT_EQ (115,
1833+ cpp_display_column_to_byte_column (str, 15, 111, def_tabstop));
1834+ ASSERT_EQ (10000,
1835+ cpp_display_column_to_byte_column (NULL, 0, 10000, def_tabstop));
1836+ ASSERT_EQ (0,
1837+ cpp_display_column_to_byte_column (NULL, 10000, 0, def_tabstop));
1838
1839 /* Verify that we do not interrupt a UTF-8 sequence. */
1840- ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 1));
1841+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 1, def_tabstop));
1842
1843 for (int byte_col = 1; byte_col <= 15; ++byte_col)
1844 {
1845- const int disp_col = cpp_byte_column_to_display_column (str, 15,
1846- byte_col);
1847- const int byte_col2 = cpp_display_column_to_byte_column (str, 15,
1848- disp_col);
1849+ const int disp_col
1850+ = cpp_byte_column_to_display_column (str, 15, byte_col, def_tabstop);
1851+ const int byte_col2
1852+ = cpp_display_column_to_byte_column (str, 15, disp_col, def_tabstop);
1853
1854 /* If we ask for the display column in the middle of a UTF-8
1855 sequence, it will return the length of the partial sequence,
1856diff --git a/gcc/input.h b/gcc/input.h
1857--- a/gcc/input.h 2020-07-22 23:35:17.664388078 -0700
1858+++ b/gcc/input.h 2021-12-25 01:20:53.487636494 -0800
1859@@ -38,7 +38,9 @@ STATIC_ASSERT (BUILTINS_LOCATION < RESER
1860
1861 extern bool is_location_from_builtin_token (location_t);
1862 extern expanded_location expand_location (location_t);
1863-extern int location_compute_display_column (expanded_location);
1864+
1865+extern int location_compute_display_column (expanded_location exploc,
1866+ int tabstop);
1867
1868 /* A class capturing the bounds of a buffer, to allow for run-time
1869 bounds-checking in a checked build. */
1870diff --git a/gcc/opts.c b/gcc/opts.c
1871--- a/gcc/opts.c 2020-07-22 23:35:17.708388562 -0700
1872+++ b/gcc/opts.c 2021-12-25 01:20:53.487636494 -0800
1873@@ -2439,6 +2439,14 @@ common_handle_option (struct gcc_options
1874 dc->parseable_fixits_p = value;
1875 break;
1876
1877+ case OPT_fdiagnostics_column_unit_:
1878+ dc->column_unit = (enum diagnostics_column_unit)value;
1879+ break;
1880+
1881+ case OPT_fdiagnostics_column_origin_:
1882+ dc->column_origin = value;
1883+ break;
1884+
1885 case OPT_fdiagnostics_show_cwe:
1886 dc->show_cwe = value;
1887 break;
1888@@ -2825,6 +2833,12 @@ common_handle_option (struct gcc_options
1889 check_alignment_argument (loc, arg, "functions");
1890 break;
1891
1892+ case OPT_ftabstop_:
1893+ /* It is documented that we silently ignore silly values. */
1894+ if (value >= 1 && value <= 100)
1895+ dc->tabstop = value;
1896+ break;
1897+
1898 default:
1899 /* If the flag was handled in a standard way, assume the lack of
1900 processing here is intentional. */
1901diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c
1902--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c 2020-07-22 23:35:17.908390765 -0700
1903+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c 2021-12-25 01:20:53.487636494 -0800
1904@@ -8,17 +8,22 @@
1905 We can't rely on any ordering of the keys. */
1906
1907 /* { dg-regexp "\"kind\": \"error\"" } */
1908+/* { dg-regexp "\"column-origin\": 1" } */
1909 /* { dg-regexp "\"message\": \"#error message\"" } */
1910
1911 /* { dg-regexp "\"caret\": \{" } */
1912 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-1.c\"" } */
1913 /* { dg-regexp "\"line\": 4" } */
1914 /* { dg-regexp "\"column\": 2" } */
1915+/* { dg-regexp "\"display-column\": 2" } */
1916+/* { dg-regexp "\"byte-column\": 2" } */
1917
1918 /* { dg-regexp "\"finish\": \{" } */
1919 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-1.c\"" } */
1920 /* { dg-regexp "\"line\": 4" } */
1921 /* { dg-regexp "\"column\": 6" } */
1922+/* { dg-regexp "\"display-column\": 6" } */
1923+/* { dg-regexp "\"byte-column\": 6" } */
1924
1925 /* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
1926 /* { dg-regexp "\"children\": \[\[\]\[\]\]" } */
1927diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c
1928--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c 2020-07-22 23:35:17.908390765 -0700
1929+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c 2021-12-25 01:20:53.487636494 -0800
1930@@ -8,6 +8,7 @@
1931 We can't rely on any ordering of the keys. */
1932
1933 /* { dg-regexp "\"kind\": \"warning\"" } */
1934+/* { dg-regexp "\"column-origin\": 1" } */
1935 /* { dg-regexp "\"message\": \"#warning message\"" } */
1936 /* { dg-regexp "\"option\": \"-Wcpp\"" } */
1937 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
1938@@ -16,11 +17,15 @@
1939 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.c\"" } */
1940 /* { dg-regexp "\"line\": 4" } */
1941 /* { dg-regexp "\"column\": 2" } */
1942+/* { dg-regexp "\"display-column\": 2" } */
1943+/* { dg-regexp "\"byte-column\": 2" } */
1944
1945 /* { dg-regexp "\"finish\": \{" } */
1946 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.c\"" } */
1947 /* { dg-regexp "\"line\": 4" } */
1948 /* { dg-regexp "\"column\": 8" } */
1949+/* { dg-regexp "\"display-column\": 8" } */
1950+/* { dg-regexp "\"byte-column\": 8" } */
1951
1952 /* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
1953 /* { dg-regexp "\"children\": \[\[\]\[\]\]" } */
1954diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c
1955--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c 2020-07-22 23:35:17.908390765 -0700
1956+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c 2021-12-25 01:20:53.487636494 -0800
1957@@ -8,6 +8,7 @@
1958 We can't rely on any ordering of the keys. */
1959
1960 /* { dg-regexp "\"kind\": \"error\"" } */
1961+/* { dg-regexp "\"column-origin\": 1" } */
1962 /* { dg-regexp "\"message\": \"#warning message\"" } */
1963 /* { dg-regexp "\"option\": \"-Werror=cpp\"" } */
1964 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
1965@@ -16,11 +17,15 @@
1966 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.c\"" } */
1967 /* { dg-regexp "\"line\": 4" } */
1968 /* { dg-regexp "\"column\": 2" } */
1969+/* { dg-regexp "\"display-column\": 2" } */
1970+/* { dg-regexp "\"byte-column\": 2" } */
1971
1972 /* { dg-regexp "\"finish\": \{" } */
1973 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.c\"" } */
1974 /* { dg-regexp "\"line\": 4" } */
1975 /* { dg-regexp "\"column\": 8" } */
1976+/* { dg-regexp "\"display-column\": 8" } */
1977+/* { dg-regexp "\"byte-column\": 8" } */
1978
1979 /* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
1980 /* { dg-regexp "\"children\": \[\[\]\[\]\]" } */
1981diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c
1982--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c 2020-07-22 23:35:17.908390765 -0700
1983+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c 2021-12-25 01:20:53.487636494 -0800
1984@@ -24,15 +24,20 @@ int test (void)
1985 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
1986 /* { dg-regexp "\"line\": 8" } */
1987 /* { dg-regexp "\"column\": 5" } */
1988+/* { dg-regexp "\"display-column\": 5" } */
1989+/* { dg-regexp "\"byte-column\": 5" } */
1990
1991 /* { dg-regexp "\"finish\": \{" } */
1992 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
1993 /* { dg-regexp "\"line\": 8" } */
1994 /* { dg-regexp "\"column\": 10" } */
1995+/* { dg-regexp "\"display-column\": 10" } */
1996+/* { dg-regexp "\"byte-column\": 10" } */
1997
1998 /* The outer diagnostic. */
1999
2000 /* { dg-regexp "\"kind\": \"warning\"" } */
2001+/* { dg-regexp "\"column-origin\": 1" } */
2002 /* { dg-regexp "\"message\": \"this 'if' clause does not guard...\"" } */
2003 /* { dg-regexp "\"option\": \"-Wmisleading-indentation\"" } */
2004 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wmisleading-indentation\"" } */
2005@@ -41,11 +46,15 @@ int test (void)
2006 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
2007 /* { dg-regexp "\"line\": 6" } */
2008 /* { dg-regexp "\"column\": 3" } */
2009+/* { dg-regexp "\"display-column\": 3" } */
2010+/* { dg-regexp "\"byte-column\": 3" } */
2011
2012 /* { dg-regexp "\"finish\": \{" } */
2013 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
2014 /* { dg-regexp "\"line\": 6" } */
2015 /* { dg-regexp "\"column\": 4" } */
2016+/* { dg-regexp "\"display-column\": 4" } */
2017+/* { dg-regexp "\"byte-column\": 4" } */
2018
2019 /* More from the nested diagnostic (we can't guarantee what order the
2020 "file" keys are consumed). */
2021diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c
2022--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c 2020-07-22 23:35:17.908390765 -0700
2023+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c 2021-12-25 01:20:53.487636494 -0800
2024@@ -13,6 +13,7 @@ int test (struct s *ptr)
2025 We can't rely on any ordering of the keys. */
2026
2027 /* { dg-regexp "\"kind\": \"error\"" } */
2028+/* { dg-regexp "\"column-origin\": 1" } */
2029 /* { dg-regexp "\"message\": \".*\"" } */
2030
2031 /* Verify fix-it hints. */
2032@@ -23,11 +24,15 @@ int test (struct s *ptr)
2033 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-5.c\"" } */
2034 /* { dg-regexp "\"line\": 8" } */
2035 /* { dg-regexp "\"column\": 15" } */
2036+/* { dg-regexp "\"display-column\": 15" } */
2037+/* { dg-regexp "\"byte-column\": 15" } */
2038
2039 /* { dg-regexp "\"next\": \{" } */
2040 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-5.c\"" } */
2041 /* { dg-regexp "\"line\": 8" } */
2042 /* { dg-regexp "\"column\": 21" } */
2043+/* { dg-regexp "\"display-column\": 21" } */
2044+/* { dg-regexp "\"byte-column\": 21" } */
2045
2046 /* { dg-regexp "\"fixits\": \[\[\{\}, \]*\]" } */
2047
2048@@ -35,11 +40,15 @@ int test (struct s *ptr)
2049 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-5.c\"" } */
2050 /* { dg-regexp "\"line\": 8" } */
2051 /* { dg-regexp "\"column\": 15" } */
2052+/* { dg-regexp "\"display-column\": 15" } */
2053+/* { dg-regexp "\"byte-column\": 15" } */
2054
2055 /* { dg-regexp "\"finish\": \{" } */
2056 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-5.c\"" } */
2057 /* { dg-regexp "\"line\": 8" } */
2058 /* { dg-regexp "\"column\": 20" } */
2059+/* { dg-regexp "\"display-column\": 20" } */
2060+/* { dg-regexp "\"byte-column\": 20" } */
2061
2062 /* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */
2063 /* { dg-regexp "\"children\": \[\[\]\[\]\]" } */
2064diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-1.c b/gcc/testsuite/c-c++-common/diagnostic-units-1.c
2065--- a/gcc/testsuite/c-c++-common/diagnostic-units-1.c 1969-12-31 16:00:00.000000000 -0800
2066+++ b/gcc/testsuite/c-c++-common/diagnostic-units-1.c 2021-12-25 01:20:53.487636494 -0800
2067@@ -0,0 +1,28 @@
2068+/* { dg-do compile } */
2069+/* { dg-additional-options "-fdiagnostics-column-unit=byte -fshow-column -fdiagnostics-show-caret -Wmultichar" } */
2070+
2071+/* column units: bytes (via arg)
2072+ column origin: 1 (via default)
2073+ tabstop: 8 (via default) */
2074+
2075+/* This line starts with a tab. */
2076+ int c1 = 'c1'; /* { dg-warning "11: multi-character character constant" } */
2077+/* { dg-begin-multiline-output "" }
2078+ int c1 = 'c1';
2079+ ^~~~
2080+ { dg-end-multiline-output "" } */
2081+
2082+/* This line starts with <tabstop> spaces. */
2083+ int c2 = 'c2'; /* { dg-warning "18: multi-character character constant" } */
2084+/* { dg-begin-multiline-output "" }
2085+ int c2 = 'c2';
2086+ ^~~~
2087+ { dg-end-multiline-output "" } */
2088+
2089+/* This line starts with <tabstop> spaces and has an internal tab after
2090+ a space. */
2091+ int c3 = 'c3'; /* { dg-warning "19: multi-character character constant" } */
2092+/* { dg-begin-multiline-output "" }
2093+ int c3 = 'c3';
2094+ ^~~~
2095+ { dg-end-multiline-output "" } */
2096diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-2.c b/gcc/testsuite/c-c++-common/diagnostic-units-2.c
2097--- a/gcc/testsuite/c-c++-common/diagnostic-units-2.c 1969-12-31 16:00:00.000000000 -0800
2098+++ b/gcc/testsuite/c-c++-common/diagnostic-units-2.c 2021-12-25 01:20:53.487636494 -0800
2099@@ -0,0 +1,28 @@
2100+/* { dg-do compile } */
2101+/* { dg-additional-options "-fdiagnostics-column-unit=display -fshow-column -fdiagnostics-show-caret -Wmultichar" } */
2102+
2103+/* column units: display (via arg)
2104+ column origin: 1 (via default)
2105+ tabstop: 8 (via default) */
2106+
2107+/* This line starts with a tab. */
2108+ int c1 = 'c1'; /* { dg-warning "18: multi-character character constant" } */
2109+/* { dg-begin-multiline-output "" }
2110+ int c1 = 'c1';
2111+ ^~~~
2112+ { dg-end-multiline-output "" } */
2113+
2114+/* This line starts with <tabstop> spaces. */
2115+ int c2 = 'c2'; /* { dg-warning "18: multi-character character constant" } */
2116+/* { dg-begin-multiline-output "" }
2117+ int c2 = 'c2';
2118+ ^~~~
2119+ { dg-end-multiline-output "" } */
2120+
2121+/* This line starts with <tabstop> spaces and has an internal tab after
2122+ a space. */
2123+ int c3 = 'c3'; /* { dg-warning "25: multi-character character constant" } */
2124+/* { dg-begin-multiline-output "" }
2125+ int c3 = 'c3';
2126+ ^~~~
2127+ { dg-end-multiline-output "" } */
2128diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-3.c b/gcc/testsuite/c-c++-common/diagnostic-units-3.c
2129--- a/gcc/testsuite/c-c++-common/diagnostic-units-3.c 1969-12-31 16:00:00.000000000 -0800
2130+++ b/gcc/testsuite/c-c++-common/diagnostic-units-3.c 2021-12-25 01:20:53.487636494 -0800
2131@@ -0,0 +1,28 @@
2132+/* { dg-do compile } */
2133+/* { dg-additional-options "-fdiagnostics-column-unit=byte -fshow-column -fdiagnostics-show-caret -ftabstop=200 -Wmultichar" } */
2134+
2135+/* column units: bytes (via arg)
2136+ column origin: 1 (via fallback from overly large argument)
2137+ tabstop: 8 (via default) */
2138+
2139+/* This line starts with a tab. */
2140+ int c1 = 'c1'; /* { dg-warning "11: multi-character character constant" } */
2141+/* { dg-begin-multiline-output "" }
2142+ int c1 = 'c1';
2143+ ^~~~
2144+ { dg-end-multiline-output "" } */
2145+
2146+/* This line starts with <tabstop> spaces. */
2147+ int c2 = 'c2'; /* { dg-warning "18: multi-character character constant" } */
2148+/* { dg-begin-multiline-output "" }
2149+ int c2 = 'c2';
2150+ ^~~~
2151+ { dg-end-multiline-output "" } */
2152+
2153+/* This line starts with <tabstop> spaces and has an internal tab after
2154+ a space. */
2155+ int c3 = 'c3'; /* { dg-warning "19: multi-character character constant" } */
2156+/* { dg-begin-multiline-output "" }
2157+ int c3 = 'c3';
2158+ ^~~~
2159+ { dg-end-multiline-output "" } */
2160diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-4.c b/gcc/testsuite/c-c++-common/diagnostic-units-4.c
2161--- a/gcc/testsuite/c-c++-common/diagnostic-units-4.c 1969-12-31 16:00:00.000000000 -0800
2162+++ b/gcc/testsuite/c-c++-common/diagnostic-units-4.c 2021-12-25 01:20:53.487636494 -0800
2163@@ -0,0 +1,28 @@
2164+/* { dg-do compile } */
2165+/* { dg-additional-options "-fdiagnostics-column-unit=byte -fshow-column -fdiagnostics-show-caret -fdiagnostics-column-origin=0 -Wmultichar" } */
2166+
2167+/* column units: bytes (via arg)
2168+ column origin: 0 (via arg)
2169+ tabstop: 8 (via default) */
2170+
2171+/* This line starts with a tab. */
2172+ int c1 = 'c1'; /* { dg-warning "10: multi-character character constant" } */
2173+/* { dg-begin-multiline-output "" }
2174+ int c1 = 'c1';
2175+ ^~~~
2176+ { dg-end-multiline-output "" } */
2177+
2178+/* This line starts with <tabstop> spaces. */
2179+ int c2 = 'c2'; /* { dg-warning "17: multi-character character constant" } */
2180+/* { dg-begin-multiline-output "" }
2181+ int c2 = 'c2';
2182+ ^~~~
2183+ { dg-end-multiline-output "" } */
2184+
2185+/* This line starts with <tabstop> spaces and has an internal tab after
2186+ a space. */
2187+ int c3 = 'c3'; /* { dg-warning "18: multi-character character constant" } */
2188+/* { dg-begin-multiline-output "" }
2189+ int c3 = 'c3';
2190+ ^~~~
2191+ { dg-end-multiline-output "" } */
2192diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-5.c b/gcc/testsuite/c-c++-common/diagnostic-units-5.c
2193--- a/gcc/testsuite/c-c++-common/diagnostic-units-5.c 1969-12-31 16:00:00.000000000 -0800
2194+++ b/gcc/testsuite/c-c++-common/diagnostic-units-5.c 2021-12-25 01:20:53.491636427 -0800
2195@@ -0,0 +1,28 @@
2196+/* { dg-do compile } */
2197+/* { dg-additional-options "-fdiagnostics-column-unit=display -fshow-column -fdiagnostics-show-caret -fdiagnostics-column-origin=0 -Wmultichar" } */
2198+
2199+/* column units: display (via arg)
2200+ column origin: 0 (via arg)
2201+ tabstop: 8 (via default) */
2202+
2203+/* This line starts with a tab. */
2204+ int c1 = 'c1'; /* { dg-warning "17: multi-character character constant" } */
2205+/* { dg-begin-multiline-output "" }
2206+ int c1 = 'c1';
2207+ ^~~~
2208+ { dg-end-multiline-output "" } */
2209+
2210+/* This line starts with <tabstop> spaces. */
2211+ int c2 = 'c2'; /* { dg-warning "17: multi-character character constant" } */
2212+/* { dg-begin-multiline-output "" }
2213+ int c2 = 'c2';
2214+ ^~~~
2215+ { dg-end-multiline-output "" } */
2216+
2217+/* This line starts with <tabstop> spaces and has an internal tab after
2218+ a space. */
2219+ int c3 = 'c3'; /* { dg-warning "24: multi-character character constant" } */
2220+/* { dg-begin-multiline-output "" }
2221+ int c3 = 'c3';
2222+ ^~~~
2223+ { dg-end-multiline-output "" } */
2224diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-6.c b/gcc/testsuite/c-c++-common/diagnostic-units-6.c
2225--- a/gcc/testsuite/c-c++-common/diagnostic-units-6.c 1969-12-31 16:00:00.000000000 -0800
2226+++ b/gcc/testsuite/c-c++-common/diagnostic-units-6.c 2021-12-25 01:20:53.491636427 -0800
2227@@ -0,0 +1,28 @@
2228+/* { dg-do compile } */
2229+/* { dg-additional-options "-fdiagnostics-column-unit=byte -fshow-column -fdiagnostics-show-caret -fdiagnostics-column-origin=100 -Wmultichar" } */
2230+
2231+/* column units: bytes (via arg)
2232+ column origin: 100 (via arg)
2233+ tabstop: 8 (via default) */
2234+
2235+/* This line starts with a tab. */
2236+ int c1 = 'c1'; /* { dg-warning "110: multi-character character constant" } */
2237+/* { dg-begin-multiline-output "" }
2238+ int c1 = 'c1';
2239+ ^~~~
2240+ { dg-end-multiline-output "" } */
2241+
2242+/* This line starts with <tabstop> spaces. */
2243+ int c2 = 'c2'; /* { dg-warning "117: multi-character character constant" } */
2244+/* { dg-begin-multiline-output "" }
2245+ int c2 = 'c2';
2246+ ^~~~
2247+ { dg-end-multiline-output "" } */
2248+
2249+/* This line starts with <tabstop> spaces and has an internal tab after
2250+ a space. */
2251+ int c3 = 'c3'; /* { dg-warning "118: multi-character character constant" } */
2252+/* { dg-begin-multiline-output "" }
2253+ int c3 = 'c3';
2254+ ^~~~
2255+ { dg-end-multiline-output "" } */
2256diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-7.c b/gcc/testsuite/c-c++-common/diagnostic-units-7.c
2257--- a/gcc/testsuite/c-c++-common/diagnostic-units-7.c 1969-12-31 16:00:00.000000000 -0800
2258+++ b/gcc/testsuite/c-c++-common/diagnostic-units-7.c 2021-12-25 01:20:53.491636427 -0800
2259@@ -0,0 +1,28 @@
2260+/* { dg-do compile } */
2261+/* { dg-additional-options "-fdiagnostics-column-unit=byte -fshow-column -fdiagnostics-show-caret -ftabstop=9 -Wmultichar" } */
2262+
2263+/* column units: bytes (via arg)
2264+ column origin: 1 (via default)
2265+ tabstop: 9 (via arg) */
2266+
2267+/* This line starts with a tab. */
2268+ int c1 = 'c1'; /* { dg-warning "11: multi-character character constant" } */
2269+/* { dg-begin-multiline-output "" }
2270+ int c1 = 'c1';
2271+ ^~~~
2272+ { dg-end-multiline-output "" } */
2273+
2274+/* This line starts with <tabstop> spaces. */
2275+ int c2 = 'c2'; /* { dg-warning "19: multi-character character constant" } */
2276+/* { dg-begin-multiline-output "" }
2277+ int c2 = 'c2';
2278+ ^~~~
2279+ { dg-end-multiline-output "" } */
2280+
2281+/* This line starts with <tabstop> spaces and has an internal tab after
2282+ a space. */
2283+ int c3 = 'c3'; /* { dg-warning "20: multi-character character constant" } */
2284+/* { dg-begin-multiline-output "" }
2285+ int c3 = 'c3';
2286+ ^~~~
2287+ { dg-end-multiline-output "" } */
2288diff --git a/gcc/testsuite/c-c++-common/diagnostic-units-8.c b/gcc/testsuite/c-c++-common/diagnostic-units-8.c
2289--- a/gcc/testsuite/c-c++-common/diagnostic-units-8.c 1969-12-31 16:00:00.000000000 -0800
2290+++ b/gcc/testsuite/c-c++-common/diagnostic-units-8.c 2021-12-25 01:20:53.491636427 -0800
2291@@ -0,0 +1,28 @@
2292+/* { dg-do compile } */
2293+/* { dg-additional-options "-fshow-column -fdiagnostics-show-caret -ftabstop=9 -Wmultichar" } */
2294+
2295+/* column units: display (via default)
2296+ column origin: 1 (via default)
2297+ tabstop: 9 (via arg) */
2298+
2299+/* This line starts with a tab. */
2300+ int c1 = 'c1'; /* { dg-warning "19: multi-character character constant" } */
2301+/* { dg-begin-multiline-output "" }
2302+ int c1 = 'c1';
2303+ ^~~~
2304+ { dg-end-multiline-output "" } */
2305+
2306+/* This line starts with <tabstop> spaces. */
2307+ int c2 = 'c2'; /* { dg-warning "19: multi-character character constant" } */
2308+/* { dg-begin-multiline-output "" }
2309+ int c2 = 'c2';
2310+ ^~~~
2311+ { dg-end-multiline-output "" } */
2312+
2313+/* This line starts with <tabstop> spaces and has an internal tab after
2314+ a space. */
2315+ int c3 = 'c3'; /* { dg-warning "28: multi-character character constant" } */
2316+/* { dg-begin-multiline-output "" }
2317+ int c3 = 'c3';
2318+ ^~~~
2319+ { dg-end-multiline-output "" } */
2320diff --git a/gcc/testsuite/c-c++-common/missing-close-symbol.c b/gcc/testsuite/c-c++-common/missing-close-symbol.c
2321--- a/gcc/testsuite/c-c++-common/missing-close-symbol.c 2020-07-22 23:35:17.912390810 -0700
2322+++ b/gcc/testsuite/c-c++-common/missing-close-symbol.c 2021-12-25 01:20:53.491636427 -0800
2323@@ -24,9 +24,9 @@ void test_static_assert_different_line (
2324 _Static_assert(sizeof(int) >= sizeof(char), /* { dg-message "to match this '\\('" } */
2325 "msg"; /* { dg-error "expected '\\)' before ';' token" } */
2326 /* { dg-begin-multiline-output "" }
2327- "msg";
2328- ^
2329- )
2330+ "msg";
2331+ ^
2332+ )
2333 { dg-end-multiline-output "" } */
2334 /* { dg-begin-multiline-output "" }
2335 _Static_assert(sizeof(int) >= sizeof(char),
2336diff --git a/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c b/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c
2337--- a/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c 2020-07-22 23:35:17.904390722 -0700
2338+++ b/gcc/testsuite/c-c++-common/Wmisleading-indentation-3.c 2021-12-25 01:20:53.487636494 -0800
2339@@ -36,20 +36,20 @@ int fn_6 (int a, int b, int c)
2340 /* ... */
2341 if ((err = foo (a)) != 0)
2342 goto fail;
2343- if ((err = foo (b)) != 0) /* { dg-message "2: this 'if' clause does not guard..." } */
2344+ if ((err = foo (b)) != 0) /* { dg-message "9: this 'if' clause does not guard..." } */
2345 goto fail;
2346- goto fail; /* { dg-message "3: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2347+ goto fail; /* { dg-message "17: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2348 if ((err = foo (c)) != 0)
2349 goto fail;
2350 /* ... */
2351
2352 /* { dg-begin-multiline-output "" }
2353- if ((err = foo (b)) != 0)
2354- ^~
2355+ if ((err = foo (b)) != 0)
2356+ ^~
2357 { dg-end-multiline-output "" } */
2358 /* { dg-begin-multiline-output "" }
2359- goto fail;
2360- ^~~~
2361+ goto fail;
2362+ ^~~~
2363 { dg-end-multiline-output "" } */
2364
2365 fail:
2366diff --git a/gcc/testsuite/c-c++-common/Wmisleading-indentation.c b/gcc/testsuite/c-c++-common/Wmisleading-indentation.c
2367--- a/gcc/testsuite/c-c++-common/Wmisleading-indentation.c 2020-07-22 23:35:17.904390722 -0700
2368+++ b/gcc/testsuite/c-c++-common/Wmisleading-indentation.c 2021-12-25 01:20:53.487636494 -0800
2369@@ -65,9 +65,9 @@ int fn_6 (int a, int b, int c)
2370 /* ... */
2371 if ((err = foo (a)) != 0)
2372 goto fail;
2373- if ((err = foo (b)) != 0) /* { dg-message "2: this 'if' clause does not guard..." } */
2374+ if ((err = foo (b)) != 0) /* { dg-message "9: this 'if' clause does not guard..." } */
2375 goto fail;
2376- goto fail; /* { dg-message "3: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2377+ goto fail; /* { dg-message "17: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2378 if ((err = foo (c)) != 0)
2379 goto fail;
2380 /* ... */
2381@@ -178,7 +178,7 @@ void fn_16_tabs (void)
2382 while (flagA)
2383 if (flagB) /* { dg-message "7: this 'if' clause does not guard..." } */
2384 foo (0);
2385- foo (1);/* { dg-message "2: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2386+ foo (1);/* { dg-message "9: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'" } */
2387 }
2388
2389 void fn_17_spaces (void)
2390diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
2391--- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c 2020-07-22 23:35:18.124393144 -0700
2392+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c 2021-12-25 01:20:53.491636427 -0800
2393@@ -288,7 +288,7 @@ int test_3 (int x, int y)
2394 | | ~~~~~~~~~~
2395 | | |
2396 | | (4) ...to here
2397- | NN | to dereference it above
2398+ | NN | to dereference it above
2399 | NN | return *ptr;
2400 | | ~~~~
2401 | | |
2402diff --git a/gcc/testsuite/gcc.dg/bad-binary-ops.c b/gcc/testsuite/gcc.dg/bad-binary-ops.c
2403--- a/gcc/testsuite/gcc.dg/bad-binary-ops.c 2020-07-22 23:35:18.128393190 -0700
2404+++ b/gcc/testsuite/gcc.dg/bad-binary-ops.c 2021-12-25 01:20:53.491636427 -0800
2405@@ -35,10 +35,10 @@ int test_2 (void)
2406 ~~~~~~~~~~~~~~~~
2407 |
2408 struct s
2409- + some_other_function ());
2410- ^ ~~~~~~~~~~~~~~~~~~~~~~
2411- |
2412- struct t
2413+ + some_other_function ());
2414+ ^ ~~~~~~~~~~~~~~~~~~~~~~
2415+ |
2416+ struct t
2417 { dg-end-multiline-output "" } */
2418 }
2419
2420diff --git a/gcc/testsuite/gcc.dg/format/branch-1.c b/gcc/testsuite/gcc.dg/format/branch-1.c
2421--- a/gcc/testsuite/gcc.dg/format/branch-1.c 2020-07-22 23:35:18.152393454 -0700
2422+++ b/gcc/testsuite/gcc.dg/format/branch-1.c 2021-12-25 01:20:53.491636427 -0800
2423@@ -10,7 +10,7 @@ foo (long l, int nfoo)
2424 {
2425 printf ((nfoo > 1) ? "%d foos" : "%d foo", nfoo);
2426 printf ((l > 1) ? "%d foos" /* { dg-warning "23:int" "wrong type in conditional expr" } */
2427- : "%d foo", l); /* { dg-warning "16:int" "wrong type in conditional expr" } */
2428+ : "%d foo", l); /* { dg-warning "23:int" "wrong type in conditional expr" } */
2429 printf ((l > 1) ? "%ld foos" : "%d foo", l); /* { dg-warning "36:int" "wrong type in conditional expr" } */
2430 printf ((l > 1) ? "%d foos" : "%ld foo", l); /* { dg-warning "23:int" "wrong type in conditional expr" } */
2431 /* Should allow one case to have extra arguments. */
2432diff --git a/gcc/testsuite/gcc.dg/format/pr79210.c b/gcc/testsuite/gcc.dg/format/pr79210.c
2433--- a/gcc/testsuite/gcc.dg/format/pr79210.c 2020-07-22 23:35:18.152393454 -0700
2434+++ b/gcc/testsuite/gcc.dg/format/pr79210.c 2021-12-25 01:20:53.491636427 -0800
2435@@ -20,4 +20,4 @@ LPFC_VPORT_ATTR_R(peer_port_login,
2436 "Allow peer ports on the same physical port to login to each "
2437 "other.");
2438
2439-/* { dg-warning "6: format .%d. expects argument of type .int., but argument 4 has type .unsigned int. " "" { target *-*-* } .-12 } */
2440+/* { dg-warning "20: format .%d. expects argument of type .int., but argument 4 has type .unsigned int. " "" { target *-*-* } .-12 } */
2441diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c
2442--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c 2020-07-22 23:35:18.172393674 -0700
2443+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-expressions-1.c 2021-12-25 01:20:53.491636427 -0800
2444@@ -540,15 +540,15 @@ void test_builtin_types_compatible_p (un
2445 __emit_expression_range (0,
2446 f (i) + __builtin_types_compatible_p (long, int)); /* { dg-warning "range" } */
2447 /* { dg-begin-multiline-output "" }
2448- f (i) + __builtin_types_compatible_p (long, int));
2449- ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2450+ f (i) + __builtin_types_compatible_p (long, int));
2451+ ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2452 { dg-end-multiline-output "" } */
2453
2454 __emit_expression_range (0,
2455 __builtin_types_compatible_p (long, int) + f (i)); /* { dg-warning "range" } */
2456 /* { dg-begin-multiline-output "" }
2457- __builtin_types_compatible_p (long, int) + f (i));
2458- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
2459+ __builtin_types_compatible_p (long, int) + f (i));
2460+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
2461 { dg-end-multiline-output "" } */
2462 }
2463
2464@@ -671,8 +671,8 @@ void test_multiple_ordinary_maps (void)
2465 /* { dg-begin-multiline-output "" }
2466 __emit_expression_range (0, foo (0,
2467 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2468- "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"));
2469- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2470+ "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"));
2471+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2472 { dg-end-multiline-output "" } */
2473
2474 /* Another expression that transitions between ordinary maps; this
2475@@ -685,8 +685,8 @@ void test_multiple_ordinary_maps (void)
2476 /* { dg-begin-multiline-output "" }
2477 __emit_expression_range (0, foo (0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789",
2478 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2479- 0));
2480- ~~
2481+ 0));
2482+ ~~
2483 { dg-end-multiline-output "" } */
2484 }
2485
2486diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c
2487--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c 2020-07-22 23:35:18.172393674 -0700
2488+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-string-literals-1.c 2021-12-25 01:20:53.491636427 -0800
2489@@ -335,11 +335,11 @@ pr87652 (const char *stem, int counter)
2490 /* { dg-error "unable to read substring location: unable to read source line" "" { target c } 329 } */
2491 /* { dg-error "unable to read substring location: failed to get ordinary maps" "" { target c++ } 329 } */
2492 /* { dg-begin-multiline-output "" }
2493- __emit_string_literal_range(__FILE__":%5d: " format, \
2494+ __emit_string_literal_range(__FILE__":%5d: " format, \
2495 ^~~~~~~~
2496 { dg-end-multiline-output "" { target c } } */
2497 /* { dg-begin-multiline-output "" }
2498- __emit_string_literal_range(__FILE__":%5d: " format, \
2499+ __emit_string_literal_range(__FILE__":%5d: " format, \
2500 ^
2501 { dg-end-multiline-output "" { target c++ } } */
2502
2503diff --git a/gcc/testsuite/gcc.dg/redecl-4.c b/gcc/testsuite/gcc.dg/redecl-4.c
2504--- a/gcc/testsuite/gcc.dg/redecl-4.c 2020-07-22 23:35:18.192393895 -0700
2505+++ b/gcc/testsuite/gcc.dg/redecl-4.c 2021-12-25 01:20:53.491636427 -0800
2506@@ -15,7 +15,7 @@ f (void)
2507 /* Should get format warnings even though the built-in declaration
2508 isn't "visible". */
2509 printf (
2510- "%s", 1); /* { dg-warning "8:format" } */
2511+ "%s", 1); /* { dg-warning "15:format" } */
2512 /* The type of strcmp here should have no prototype. */
2513 if (0)
2514 strcmp (1);
2515diff --git a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C
2516--- a/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C 2020-07-22 23:35:17.972391472 -0700
2517+++ b/gcc/testsuite/g++.dg/diagnostic/bad-binary-ops.C 2021-12-25 01:20:53.491636427 -0800
2518@@ -33,10 +33,10 @@ int test_2 (void)
2519 ~~~~~~~~~~~~~~~~
2520 |
2521 s
2522- + some_other_function ());
2523- ^ ~~~~~~~~~~~~~~~~~~~~~~
2524- |
2525- t
2526+ + some_other_function ());
2527+ ^ ~~~~~~~~~~~~~~~~~~~~~~
2528+ |
2529+ t
2530 { dg-end-multiline-output "" } */
2531 }
2532
2533diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C
2534--- a/gcc/testsuite/g++.dg/parse/error4.C 2020-07-22 23:35:18.012391910 -0700
2535+++ b/gcc/testsuite/g++.dg/parse/error4.C 2021-12-25 01:20:53.491636427 -0800
2536@@ -7,4 +7,4 @@ struct X {
2537 int);
2538 };
2539
2540-// { dg-error "4:'itn' has not been declared" "" { target *-*-* } 6 }
2541+// { dg-error "18:'itn' has not been declared" "" { target *-*-* } 6 }
2542diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90
2543--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 2020-07-22 23:35:18.512397420 -0700
2544+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 2021-12-25 01:20:53.491636427 -0800
2545@@ -8,17 +8,22 @@
2546 ! We can't rely on any ordering of the keys.
2547
2548 ! { dg-regexp "\"kind\": \"error\"" }
2549+! { dg-regexp "\"column-origin\": 1" }
2550 ! { dg-regexp "\"message\": \"#error message\"" }
2551
2552 ! { dg-regexp "\"caret\": \{" }
2553 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-1.F90\"" }
2554 ! { dg-regexp "\"line\": 4" }
2555 ! { dg-regexp "\"column\": 2" }
2556+! { dg-regexp "\"display-column\": 2" }
2557+! { dg-regexp "\"byte-column\": 2" }
2558
2559 ! { dg-regexp "\"finish\": \{" }
2560 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-1.F90\"" }
2561 ! { dg-regexp "\"line\": 4" }
2562 ! { dg-regexp "\"column\": 6" }
2563+! { dg-regexp "\"display-column\": 6" }
2564+! { dg-regexp "\"byte-column\": 6" }
2565
2566 ! { dg-regexp "\"locations\": \[\[\{\}, \]*\]" }
2567 ! { dg-regexp "\"children\": \[\[\]\[\]\]" }
2568diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90
2569--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 2020-07-22 23:35:18.512397420 -0700
2570+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 2021-12-25 01:20:53.491636427 -0800
2571@@ -8,6 +8,7 @@
2572 ! We can't rely on any ordering of the keys.
2573
2574 ! { dg-regexp "\"kind\": \"warning\"" }
2575+! { dg-regexp "\"column-origin\": 1" }
2576 ! { dg-regexp "\"message\": \"#warning message\"" }
2577 ! { dg-regexp "\"option\": \"-Wcpp\"" }
2578 ! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
2579@@ -16,11 +17,15 @@
2580 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.F90\"" }
2581 ! { dg-regexp "\"line\": 4" }
2582 ! { dg-regexp "\"column\": 2" }
2583+! { dg-regexp "\"display-column\": 2" }
2584+! { dg-regexp "\"byte-column\": 2" }
2585
2586 ! { dg-regexp "\"finish\": \{" }
2587 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-2.F90\"" }
2588 ! { dg-regexp "\"line\": 4" }
2589 ! { dg-regexp "\"column\": 8" }
2590+! { dg-regexp "\"display-column\": 8" }
2591+! { dg-regexp "\"byte-column\": 8" }
2592
2593 ! { dg-regexp "\"locations\": \[\[\{\}, \]*\]" }
2594 ! { dg-regexp "\"children\": \[\[\]\[\]\]" }
2595diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90
2596--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 2020-07-22 23:35:18.512397420 -0700
2597+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 2021-12-25 01:20:53.491636427 -0800
2598@@ -8,6 +8,7 @@
2599 ! We can't rely on any ordering of the keys.
2600
2601 ! { dg-regexp "\"kind\": \"error\"" }
2602+! { dg-regexp "\"column-origin\": 1" }
2603 ! { dg-regexp "\"message\": \"#warning message\"" }
2604 ! { dg-regexp "\"option\": \"-Werror=cpp\"" }
2605 ! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
2606@@ -16,11 +17,15 @@
2607 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.F90\"" }
2608 ! { dg-regexp "\"line\": 4" }
2609 ! { dg-regexp "\"column\": 2" }
2610+! { dg-regexp "\"display-column\": 2" }
2611+! { dg-regexp "\"byte-column\": 2" }
2612
2613 ! { dg-regexp "\"finish\": \{" }
2614 ! { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-3.F90\"" }
2615 ! { dg-regexp "\"line\": 4" }
2616 ! { dg-regexp "\"column\": 8" }
2617+! { dg-regexp "\"display-column\": 8" }
2618+! { dg-regexp "\"byte-column\": 8" }
2619
2620 ! { dg-regexp "\"locations\": \[\[\{\}, \]*\]" }
2621 ! { dg-regexp "\"children\": \[\[\]\[\]\]" }
2622diff --git a/gcc/testsuite/go.dg/arrayclear.go b/gcc/testsuite/go.dg/arrayclear.go
2623--- a/gcc/testsuite/go.dg/arrayclear.go 2020-07-22 23:35:18.588398257 -0700
2624+++ b/gcc/testsuite/go.dg/arrayclear.go 2021-12-25 01:20:53.491636427 -0800
2625@@ -1,5 +1,8 @@
2626 // { dg-do compile }
2627 // { dg-options "-fgo-debug-optimization" }
2628+// This comment is necessary to work around a dejagnu bug. Otherwise, the
2629+// column of the second error message would equal the row of the first one, and
2630+// since the errors are also identical, dejagnu is not able to distinguish them.
2631
2632 package p
2633
2634diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C
2635--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C 2020-07-22 23:35:18.048392308 -0700
2636+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash11.C 2021-12-25 01:20:53.491636427 -0800
2637@@ -9,13 +9,13 @@ class A {
2638 int h;
2639 A() { i=10; j=20; }
2640 virtual void f1() { printf("i=%d j=%d\n",i,j); }
2641- friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "9:virtual functions cannot be friends" }
2642+ friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "16:virtual functions cannot be friends" }
2643 };
2644
2645 class B : public A {
2646 public:
2647 virtual void f1() { printf("i=%d j=%d\n",i,j); }// { dg-error "" } member.*// ERROR - member.*
2648- friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "9:virtual functions cannot be friends" }
2649+ friend virtual void f2() { printf("i=%d j=%d\n",i,j); } // { dg-error "16:virtual functions cannot be friends" }
2650 // { dg-error "private" "" { target *-*-* } .-1 }
2651 };
2652
2653diff --git a/gcc/testsuite/g++.old-deja/g++.pt/overload2.C b/gcc/testsuite/g++.old-deja/g++.pt/overload2.C
2654--- a/gcc/testsuite/g++.old-deja/g++.pt/overload2.C 2020-07-22 23:35:18.072392572 -0700
2655+++ b/gcc/testsuite/g++.old-deja/g++.pt/overload2.C 2021-12-25 01:20:53.491636427 -0800
2656@@ -12,5 +12,5 @@ int
2657 main()
2658 {
2659 C<char*> c;
2660- char* p = Z(c.O); //{ dg-error "13:'Z' was not declared" } ambiguous c.O
2661+ char* p = Z(c.O); //{ dg-error "29:'Z' was not declared" } ambiguous c.O
2662 }
2663diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C
2664--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C 2020-07-22 23:35:18.076392617 -0700
2665+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C 2021-12-25 01:20:53.491636427 -0800
2666@@ -48,8 +48,8 @@ ostream& operator<<(ostream& os, Graph<V
2667
2668 // The compiler does not like this line!!!!!!
2669 typename Graph<VertexType, EdgeType>::Successor::iterator
2670- startN = G[i].second.begin(), // { dg-error "14:no match" } no index operator
2671- endN = G[i].second.end(); // { dg-error "14:no match" } no index operator
2672+ startN = G[i].second.begin(), // { dg-error "21:no match" } no index operator
2673+ endN = G[i].second.end(); // { dg-error "21:no match" } no index operator
2674
2675 while(startN != endN)
2676 {
2677diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
2678--- a/gcc/tree-diagnostic-path.cc 2020-07-22 23:35:18.628398698 -0700
2679+++ b/gcc/tree-diagnostic-path.cc 2021-12-25 01:20:53.491636427 -0800
2680@@ -493,7 +493,7 @@ default_tree_diagnostic_path_printer (di
2681 doesn't have access to trees (for m_fndecl). */
2682
2683 json::value *
2684-default_tree_make_json_for_path (diagnostic_context *,
2685+default_tree_make_json_for_path (diagnostic_context *context,
2686 const diagnostic_path *path)
2687 {
2688 json::array *path_array = new json::array ();
2689@@ -504,7 +504,8 @@ default_tree_make_json_for_path (diagnos
2690 json::object *event_obj = new json::object ();
2691 if (event.get_location ())
2692 event_obj->set ("location",
2693- json_from_expanded_location (event.get_location ()));
2694+ json_from_expanded_location (context,
2695+ event.get_location ()));
2696 label_text event_text (event.get_desc (false));
2697 event_obj->set ("description", new json::string (event_text.m_buffer));
2698 event_text.maybe_free ();
2699diff --git a/libcpp/charset.c b/libcpp/charset.c
2700--- a/libcpp/charset.c 2020-07-22 23:35:18.712399623 -0700
2701+++ b/libcpp/charset.c 2021-12-25 01:20:53.491636427 -0800
2702@@ -2276,49 +2276,90 @@ cpp_string_location_reader::get_next ()
2703 return result;
2704 }
2705
2706-/* Helper for cpp_byte_column_to_display_column and its inverse. Given a
2707- pointer to a UTF-8-encoded character, compute its display width. *INBUFP
2708- points on entry to the start of the UTF-8 encoding of the character, and
2709- is updated to point just after the last byte of the encoding. *INBYTESLEFTP
2710- contains on entry the remaining size of the buffer into which *INBUFP
2711- points, and this is also updated accordingly. If *INBUFP does not
2712+cpp_display_width_computation::
2713+cpp_display_width_computation (const char *data, int data_length, int tabstop) :
2714+ m_begin (data),
2715+ m_next (m_begin),
2716+ m_bytes_left (data_length),
2717+ m_tabstop (tabstop),
2718+ m_display_cols (0)
2719+{
2720+ gcc_assert (m_tabstop > 0);
2721+}
2722+
2723+
2724+/* The main implementation function for class cpp_display_width_computation.
2725+ m_next points on entry to the start of the UTF-8 encoding of the next
2726+ character, and is updated to point just after the last byte of the encoding.
2727+ m_bytes_left contains on entry the remaining size of the buffer into which
2728+ m_next points, and this is also updated accordingly. If m_next does not
2729 point to a valid UTF-8-encoded sequence, then it will be treated as a single
2730- byte with display width 1. */
2731+ byte with display width 1. m_cur_display_col is the current display column,
2732+ relative to which tab stops should be expanded. Returns the display width of
2733+ the codepoint just processed. */
2734
2735-static inline int
2736-compute_next_display_width (const uchar **inbufp, size_t *inbytesleftp)
2737+int
2738+cpp_display_width_computation::process_next_codepoint ()
2739 {
2740 cppchar_t c;
2741- if (one_utf8_to_cppchar (inbufp, inbytesleftp, &c) != 0)
2742+ int next_width;
2743+
2744+ if (*m_next == '\t')
2745+ {
2746+ ++m_next;
2747+ --m_bytes_left;
2748+ next_width = m_tabstop - (m_display_cols % m_tabstop);
2749+ }
2750+ else if (one_utf8_to_cppchar ((const uchar **) &m_next, &m_bytes_left, &c)
2751+ != 0)
2752 {
2753 /* Input is not convertible to UTF-8. This could be fine, e.g. in a
2754 string literal, so don't complain. Just treat it as if it has a width
2755 of one. */
2756- ++*inbufp;
2757- --*inbytesleftp;
2758- return 1;
2759+ ++m_next;
2760+ --m_bytes_left;
2761+ next_width = 1;
2762+ }
2763+ else
2764+ {
2765+ /* one_utf8_to_cppchar() has updated m_next and m_bytes_left for us. */
2766+ next_width = cpp_wcwidth (c);
2767 }
2768
2769- /* one_utf8_to_cppchar() has updated inbufp and inbytesleftp for us. */
2770- return cpp_wcwidth (c);
2771+ m_display_cols += next_width;
2772+ return next_width;
2773+}
2774+
2775+/* Utility to advance the byte stream by the minimum amount needed to consume
2776+ N display columns. Returns the number of display columns that were
2777+ actually skipped. This could be less than N, if there was not enough data,
2778+ or more than N, if the last character to be skipped had a sufficiently large
2779+ display width. */
2780+int
2781+cpp_display_width_computation::advance_display_cols (int n)
2782+{
2783+ const int start = m_display_cols;
2784+ const int target = start + n;
2785+ while (m_display_cols < target && !done ())
2786+ process_next_codepoint ();
2787+ return m_display_cols - start;
2788 }
2789
2790 /* For the string of length DATA_LENGTH bytes that begins at DATA, compute
2791 how many display columns are occupied by the first COLUMN bytes. COLUMN
2792 may exceed DATA_LENGTH, in which case the phantom bytes at the end are
2793- treated as if they have display width 1. */
2794+ treated as if they have display width 1. Tabs are expanded to the next tab
2795+ stop, relative to the start of DATA. */
2796
2797 int
2798 cpp_byte_column_to_display_column (const char *data, int data_length,
2799- int column)
2800+ int column, int tabstop)
2801 {
2802- int display_col = 0;
2803- const uchar *udata = (const uchar *) data;
2804 const int offset = MAX (0, column - data_length);
2805- size_t inbytesleft = column - offset;
2806- while (inbytesleft)
2807- display_col += compute_next_display_width (&udata, &inbytesleft);
2808- return display_col + offset;
2809+ cpp_display_width_computation dw (data, column - offset, tabstop);
2810+ while (!dw.done ())
2811+ dw.process_next_codepoint ();
2812+ return dw.display_cols_processed () + offset;
2813 }
2814
2815 /* For the string of length DATA_LENGTH bytes that begins at DATA, compute
2816@@ -2328,14 +2369,11 @@ cpp_byte_column_to_display_column (const
2817
2818 int
2819 cpp_display_column_to_byte_column (const char *data, int data_length,
2820- int display_col)
2821+ int display_col, int tabstop)
2822 {
2823- int column = 0;
2824- const uchar *udata = (const uchar *) data;
2825- size_t inbytesleft = data_length;
2826- while (column < display_col && inbytesleft)
2827- column += compute_next_display_width (&udata, &inbytesleft);
2828- return data_length - inbytesleft + MAX (0, display_col - column);
2829+ cpp_display_width_computation dw (data, data_length, tabstop);
2830+ const int avail_display = dw.advance_display_cols (display_col);
2831+ return dw.bytes_processed () + MAX (0, display_col - avail_display);
2832 }
2833
2834 /* Our own version of wcwidth(). We don't use the actual wcwidth() in glibc,
2835diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
2836--- a/libcpp/include/cpplib.h 2020-07-22 23:35:18.712399623 -0700
2837+++ b/libcpp/include/cpplib.h 2021-12-25 01:20:53.491636427 -0800
2838@@ -312,9 +312,6 @@ enum cpp_normalize_level {
2839 carries all the options visible to the command line. */
2840 struct cpp_options
2841 {
2842- /* Characters between tab stops. */
2843- unsigned int tabstop;
2844-
2845 /* The language we're preprocessing. */
2846 enum c_lang lang;
2847
2848@@ -1322,14 +1319,43 @@ extern const char * cpp_get_userdef_suff
2849 (const cpp_token *);
2850
2851 /* In charset.c */
2852+
2853+/* A class to manage the state while converting a UTF-8 sequence to cppchar_t
2854+ and computing the display width one character at a time. */
2855+class cpp_display_width_computation {
2856+ public:
2857+ cpp_display_width_computation (const char *data, int data_length,
2858+ int tabstop);
2859+ const char *next_byte () const { return m_next; }
2860+ int bytes_processed () const { return m_next - m_begin; }
2861+ int bytes_left () const { return m_bytes_left; }
2862+ bool done () const { return !bytes_left (); }
2863+ int display_cols_processed () const { return m_display_cols; }
2864+
2865+ int process_next_codepoint ();
2866+ int advance_display_cols (int n);
2867+
2868+ private:
2869+ const char *const m_begin;
2870+ const char *m_next;
2871+ size_t m_bytes_left;
2872+ const int m_tabstop;
2873+ int m_display_cols;
2874+};
2875+
2876+/* Convenience functions that are simple use cases for class
2877+ cpp_display_width_computation. Tab characters will be expanded to spaces
2878+ as determined by TABSTOP. */
2879 int cpp_byte_column_to_display_column (const char *data, int data_length,
2880- int column);
2881-inline int cpp_display_width (const char *data, int data_length)
2882+ int column, int tabstop);
2883+inline int cpp_display_width (const char *data, int data_length,
2884+ int tabstop)
2885 {
2886- return cpp_byte_column_to_display_column (data, data_length, data_length);
2887+ return cpp_byte_column_to_display_column (data, data_length, data_length,
2888+ tabstop);
2889 }
2890 int cpp_display_column_to_byte_column (const char *data, int data_length,
2891- int display_col);
2892+ int display_col, int tabstop);
2893 int cpp_wcwidth (cppchar_t c);
2894
2895 #endif /* ! LIBCPP_CPPLIB_H */
2896diff --git a/libcpp/init.c b/libcpp/init.c
2897--- a/libcpp/init.c 2020-07-22 23:35:18.712399623 -0700
2898+++ b/libcpp/init.c 2021-12-25 01:20:53.491636427 -0800
2899@@ -190,7 +190,6 @@ cpp_create_reader (enum c_lang lang, cpp
2900 CPP_OPTION (pfile, discard_comments) = 1;
2901 CPP_OPTION (pfile, discard_comments_in_macro_exp) = 1;
2902 CPP_OPTION (pfile, max_include_depth) = 200;
2903- CPP_OPTION (pfile, tabstop) = 8;
2904 CPP_OPTION (pfile, operator_names) = 1;
2905 CPP_OPTION (pfile, warn_trigraphs) = 2;
2906 CPP_OPTION (pfile, warn_endif_labels) = 1;
diff --git a/meta/recipes-devtools/gcc/gcc/0001-aarch64-Fix-up-__aarch64_cas16_acq_rel-fallback.patch b/meta/recipes-devtools/gcc/gcc/0001-aarch64-Fix-up-__aarch64_cas16_acq_rel-fallback.patch
deleted file mode 100644
index c060accd99..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0001-aarch64-Fix-up-__aarch64_cas16_acq_rel-fallback.patch
+++ /dev/null
@@ -1,66 +0,0 @@
1Upstream-Status: Backport
2Signed-off-by: Ross Burton <ross.burton@arm.com>
3
4From fd2ec4542fd2975e6d3f2f1c1a2639945a84f9e1 Mon Sep 17 00:00:00 2001
5From: Jakub Jelinek <jakub@redhat.com>
6Date: Mon, 3 Aug 2020 22:55:28 +0200
7Subject: [PATCH] aarch64: Fix up __aarch64_cas16_acq_rel fallback
8
9As mentioned in the PR, the fallback path when LSE is unavailable writes
10incorrect registers to the memory if the previous content compares equal
11to x0, x1 - it writes copy of x0, x1 from the start of function, but it
12should write x2, x3.
13
142020-08-03 Jakub Jelinek <jakub@redhat.com>
15
16 PR target/96402
17 * config/aarch64/lse.S (__aarch64_cas16_acq_rel): Use x2, x3 instead
18 of x(tmp0), x(tmp1) in STXP arguments.
19
20 * gcc.target/aarch64/pr96402.c: New test.
21
22(cherry picked from commit 90b43856fdff7d96d93d22970eca8a86c56e0ddc)
23---
24 gcc/testsuite/gcc.target/aarch64/pr96402.c | 16 ++++++++++++++++
25 libgcc/config/aarch64/lse.S | 2 +-
26 2 files changed, 17 insertions(+), 1 deletion(-)
27 create mode 100644 gcc/testsuite/gcc.target/aarch64/pr96402.c
28
29diff --git a/gcc/testsuite/gcc.target/aarch64/pr96402.c b/gcc/testsuite/gcc.target/aarch64/pr96402.c
30new file mode 100644
31index 00000000000..fa2dddfac15
32--- /dev/null
33+++ b/gcc/testsuite/gcc.target/aarch64/pr96402.c
34@@ -0,0 +1,16 @@
35+/* PR target/96402 */
36+/* { dg-do run { target int128 } } */
37+/* { dg-options "-moutline-atomics" } */
38+
39+int
40+main ()
41+{
42+ __int128 a = 0;
43+ __sync_val_compare_and_swap (&a, (__int128) 0, (__int128) 1);
44+ if (a != 1)
45+ __builtin_abort ();
46+ __sync_val_compare_and_swap (&a, (__int128) 1, (((__int128) 0xdeadbeeffeedbac1ULL) << 64) | 0xabadcafe00c0ffeeULL);
47+ if (a != ((((__int128) 0xdeadbeeffeedbac1ULL) << 64) | 0xabadcafe00c0ffeeULL))
48+ __builtin_abort ();
49+ return 0;
50+}
51diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
52index 64691c601c1..c8fbfbce4fd 100644
53--- a/libgcc/config/aarch64/lse.S
54+++ b/libgcc/config/aarch64/lse.S
55@@ -203,7 +203,7 @@ STARTFN NAME(cas)
56 cmp x0, x(tmp0)
57 ccmp x1, x(tmp1), #0, eq
58 bne 1f
59- STXP w(tmp2), x(tmp0), x(tmp1), [x4]
60+ STXP w(tmp2), x2, x3, [x4]
61 cbnz w(tmp2), 0b
62 1: ret
63
64--
652.26.2
66
diff --git a/meta/recipes-devtools/gcc/gcc/0001-aarch64-New-Straight-Line-Speculation-SLS-mitigation.patch b/meta/recipes-devtools/gcc/gcc/0001-aarch64-New-Straight-Line-Speculation-SLS-mitigation.patch
deleted file mode 100644
index 73de4c7590..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0001-aarch64-New-Straight-Line-Speculation-SLS-mitigation.patch
+++ /dev/null
@@ -1,202 +0,0 @@
1CVE: CVE-2020-13844
2Upstream-Status: Backport
3Signed-off-by: Ross Burton <ross.burton@arm.com>
4
5From 1ff243934ac443b5f58cd02a5012ce58ecc31fb2 Mon Sep 17 00:00:00 2001
6From: Matthew Malcomson <matthew.malcomson@arm.com>
7Date: Thu, 9 Jul 2020 09:11:58 +0100
8Subject: [PATCH 1/3] aarch64: New Straight Line Speculation (SLS) mitigation
9 flags
10
11Here we introduce the flags that will be used for straight line speculation.
12
13The new flag introduced is `-mharden-sls=`.
14This flag can take arguments of `none`, `all`, or a comma seperated list of one
15or more of `retbr` or `blr`.
16`none` indicates no special mitigation of the straight line speculation
17vulnerability.
18`all` requests all mitigations currently implemented.
19`retbr` requests that the RET and BR instructions have a speculation barrier
20inserted after them.
21`blr` requests that BLR instructions are replaced by a BL to a function stub
22using a BR with a speculation barrier after it.
23
24Setting this on a per-function basis using attributes or the like is not
25enabled, but may be in the future.
26
27gcc/ChangeLog:
28
292020-06-02 Matthew Malcomson <matthew.malcomson@arm.com>
30
31 * config/aarch64/aarch64-protos.h (aarch64_harden_sls_retbr_p):
32 New.
33 (aarch64_harden_sls_blr_p): New.
34 * config/aarch64/aarch64.c (enum aarch64_sls_hardening_type):
35 New.
36 (aarch64_harden_sls_retbr_p): New.
37 (aarch64_harden_sls_blr_p): New.
38 (aarch64_validate_sls_mitigation): New.
39 (aarch64_override_options): Parse options for SLS mitigation.
40 * config/aarch64/aarch64.opt (-mharden-sls): New option.
41 * doc/invoke.texi: Document new option.
42---
43 gcc/config/aarch64/aarch64-protos.h | 3 ++
44 gcc/config/aarch64/aarch64.c | 76 +++++++++++++++++++++++++++++++++++++
45 gcc/config/aarch64/aarch64.opt | 4 ++
46 gcc/doc/invoke.texi | 12 ++++++
47 4 files changed, 95 insertions(+)
48
49diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
50index 723d9ba..eb5f4b4 100644
51--- a/gcc/config/aarch64/aarch64-protos.h
52+++ b/gcc/config/aarch64/aarch64-protos.h
53@@ -781,4 +781,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
54
55 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
56
57+extern bool aarch64_harden_sls_retbr_p (void);
58+extern bool aarch64_harden_sls_blr_p (void);
59+
60 #endif /* GCC_AARCH64_PROTOS_H */
61diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
62index b86434a..437a9cf 100644
63--- a/gcc/config/aarch64/aarch64.c
64+++ b/gcc/config/aarch64/aarch64.c
65@@ -14494,6 +14494,79 @@ aarch64_validate_mcpu (const char *str, const struct processor **res,
66 return false;
67 }
68
69+/* Straight line speculation indicators. */
70+enum aarch64_sls_hardening_type
71+{
72+ SLS_NONE = 0,
73+ SLS_RETBR = 1,
74+ SLS_BLR = 2,
75+ SLS_ALL = 3,
76+};
77+static enum aarch64_sls_hardening_type aarch64_sls_hardening;
78+
79+/* Return whether we should mitigatate Straight Line Speculation for the RET
80+ and BR instructions. */
81+bool
82+aarch64_harden_sls_retbr_p (void)
83+{
84+ return aarch64_sls_hardening & SLS_RETBR;
85+}
86+
87+/* Return whether we should mitigatate Straight Line Speculation for the BLR
88+ instruction. */
89+bool
90+aarch64_harden_sls_blr_p (void)
91+{
92+ return aarch64_sls_hardening & SLS_BLR;
93+}
94+
95+/* As of yet we only allow setting these options globally, in the future we may
96+ allow setting them per function. */
97+static void
98+aarch64_validate_sls_mitigation (const char *const_str)
99+{
100+ char *token_save = NULL;
101+ char *str = NULL;
102+
103+ if (strcmp (const_str, "none") == 0)
104+ {
105+ aarch64_sls_hardening = SLS_NONE;
106+ return;
107+ }
108+ if (strcmp (const_str, "all") == 0)
109+ {
110+ aarch64_sls_hardening = SLS_ALL;
111+ return;
112+ }
113+
114+ char *str_root = xstrdup (const_str);
115+ str = strtok_r (str_root, ",", &token_save);
116+ if (!str)
117+ error ("invalid argument given to %<-mharden-sls=%>");
118+
119+ int temp = SLS_NONE;
120+ while (str)
121+ {
122+ if (strcmp (str, "blr") == 0)
123+ temp |= SLS_BLR;
124+ else if (strcmp (str, "retbr") == 0)
125+ temp |= SLS_RETBR;
126+ else if (strcmp (str, "none") == 0 || strcmp (str, "all") == 0)
127+ {
128+ error ("%<%s%> must be by itself for %<-mharden-sls=%>", str);
129+ break;
130+ }
131+ else
132+ {
133+ error ("invalid argument %<%s%> for %<-mharden-sls=%>", str);
134+ break;
135+ }
136+ str = strtok_r (NULL, ",", &token_save);
137+ }
138+ aarch64_sls_hardening = (aarch64_sls_hardening_type) temp;
139+ free (str_root);
140+}
141+
142 /* Parses CONST_STR for branch protection features specified in
143 aarch64_branch_protect_types, and set any global variables required. Returns
144 the parsing result and assigns LAST_STR to the last processed token from
145@@ -14738,6 +14811,9 @@ aarch64_override_options (void)
146 selected_arch = NULL;
147 selected_tune = NULL;
148
149+ if (aarch64_harden_sls_string)
150+ aarch64_validate_sls_mitigation (aarch64_harden_sls_string);
151+
152 if (aarch64_branch_protection_string)
153 aarch64_validate_mbranch_protection (aarch64_branch_protection_string);
154
155diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt
156index d99d14c..5170361 100644
157--- a/gcc/config/aarch64/aarch64.opt
158+++ b/gcc/config/aarch64/aarch64.opt
159@@ -71,6 +71,10 @@ mgeneral-regs-only
160 Target Report RejectNegative Mask(GENERAL_REGS_ONLY) Save
161 Generate code which uses only the general registers.
162
163+mharden-sls=
164+Target RejectNegative Joined Var(aarch64_harden_sls_string)
165+Generate code to mitigate against straight line speculation.
166+
167 mfix-cortex-a53-835769
168 Target Report Var(aarch64_fix_a53_err835769) Init(2) Save
169 Workaround for ARM Cortex-A53 Erratum number 835769.
170diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
171index a2794a6..bd5b77a 100644
172--- a/gcc/doc/invoke.texi
173+++ b/gcc/doc/invoke.texi
174@@ -696,6 +696,7 @@ Objective-C and Objective-C++ Dialects}.
175 -msign-return-address=@var{scope} @gol
176 -mbranch-protection=@var{none}|@var{standard}|@var{pac-ret}[+@var{leaf}
177 +@var{b-key}]|@var{bti} @gol
178+-mharden-sls=@var{opts} @gol
179 -march=@var{name} -mcpu=@var{name} -mtune=@var{name} @gol
180 -moverride=@var{string} -mverbose-cost-dump @gol
181 -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol
182@@ -17065,6 +17066,17 @@ functions. The optional argument @samp{b-key} can be used to sign the functions
183 with the B-key instead of the A-key.
184 @samp{bti} turns on branch target identification mechanism.
185
186+@item -mharden-sls=@var{opts}
187+@opindex mharden-sls
188+Enable compiler hardening against straight line speculation (SLS).
189+@var{opts} is a comma-separated list of the following options:
190+@table @samp
191+@item retbr
192+@item blr
193+@end table
194+In addition, @samp{-mharden-sls=all} enables all SLS hardening while
195+@samp{-mharden-sls=none} disables all SLS hardening.
196+
197 @item -msve-vector-bits=@var{bits}
198 @opindex msve-vector-bits
199 Specify the number of bits in an SVE vector register. This option only has
200--
2012.7.4
202
diff --git a/meta/recipes-devtools/gcc/gcc/0002-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0002-CVE-2021-42574.patch
new file mode 100644
index 0000000000..5b1896ed69
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0002-CVE-2021-42574.patch
@@ -0,0 +1,2270 @@
1From bd5e882cf6e0def3dd1bc106075d59a303fe0d1e Mon Sep 17 00:00:00 2001
2From: David Malcolm <dmalcolm@redhat.com>
3Date: Mon, 18 Oct 2021 18:55:31 -0400
4Subject: [PATCH] diagnostics: escape non-ASCII source bytes for certain
5 diagnostics
6MIME-Version: 1.0
7Content-Type: text/plain; charset=utf8
8Content-Transfer-Encoding: 8bit
9
10This patch adds support to GCC's diagnostic subsystem for escaping certain
11bytes and Unicode characters when quoting source code.
12
13Specifically, this patch adds a new flag rich_location::m_escape_on_output
14which is a hint from a diagnostic that non-ASCII bytes in the pertinent
15lines of the user's source code should be escaped when printed.
16
17The patch sets this for the following diagnostics:
18- when complaining about stray bytes in the program (when these
19are non-printable)
20- when complaining about "null character(s) ignored");
21- for -Wnormalized= (and generate source ranges for such warnings)
22
23The escaping is controlled by a new option:
24 -fdiagnostics-escape-format=[unicode|bytes]
25
26For example, consider a diagnostic involing a source line containing the
27string "before" followed by the Unicode character U+03C0 ("GREEK SMALL
28LETTER PI", with UTF-8 encoding 0xCF 0x80) followed by the byte 0xBF
29(a stray UTF-8 trailing byte), followed by the string "after", where the
30diagnostic highlights the U+03C0 character.
31
32By default, this line will be printed verbatim to the user when
33reporting a diagnostic at it, as:
34
35 beforeÏXafter
36 ^
37
38(using X for the stray byte to avoid putting invalid UTF-8 in this
39commit message)
40
41If the diagnostic sets the "escape" flag, it will be printed as:
42
43 before<U+03C0><BF>after
44 ^~~~~~~~
45
46with -fdiagnostics-escape-format=unicode (the default), or as:
47
48 before<CF><80><BF>after
49 ^~~~~~~~
50
51if the user supplies -fdiagnostics-escape-format=bytes.
52
53This only affects how the source is printed; it does not affect
54how column numbers that are printed (as per -fdiagnostics-column-unit=
55and -fdiagnostics-column-origin=).
56
57gcc/c-family/ChangeLog:
58 * c-lex.c (c_lex_with_flags): When complaining about non-printable
59 CPP_OTHER tokens, set the "escape on output" flag.
60
61gcc/ChangeLog:
62 * common.opt (fdiagnostics-escape-format=): New.
63 (diagnostics_escape_format): New enum.
64 (DIAGNOSTICS_ESCAPE_FORMAT_UNICODE): New enum value.
65 (DIAGNOSTICS_ESCAPE_FORMAT_BYTES): Likewise.
66 * diagnostic-format-json.cc (json_end_diagnostic): Add
67 "escape-source" attribute.
68 * diagnostic-show-locus.c
69 (exploc_with_display_col::exploc_with_display_col): Replace
70 "tabstop" param with a cpp_char_column_policy and add an "aspect"
71 param. Use these to compute m_display_col accordingly.
72 (struct char_display_policy): New struct.
73 (layout::m_policy): New field.
74 (layout::m_escape_on_output): New field.
75 (def_policy): New function.
76 (make_range): Update for changes to exploc_with_display_col ctor.
77 (default_print_decoded_ch): New.
78 (width_per_escaped_byte): New.
79 (escape_as_bytes_width): New.
80 (escape_as_bytes_print): New.
81 (escape_as_unicode_width): New.
82 (escape_as_unicode_print): New.
83 (make_policy): New.
84 (layout::layout): Initialize new fields. Update m_exploc ctor
85 call for above change to ctor.
86 (layout::maybe_add_location_range): Update for changes to
87 exploc_with_display_col ctor.
88 (layout::calculate_x_offset_display): Update for change to
89 cpp_display_width.
90 (layout::print_source_line): Pass policy
91 to cpp_display_width_computation. Capture cpp_decoded_char when
92 calling process_next_codepoint. Move printing of source code to
93 m_policy.m_print_cb.
94 (line_label::line_label): Pass in policy rather than context.
95 (layout::print_any_labels): Update for change to line_label ctor.
96 (get_affected_range): Pass in policy rather than context, updating
97 calls to location_compute_display_column accordingly.
98 (get_printed_columns): Likewise, also for cpp_display_width.
99 (correction::correction): Pass in policy rather than tabstop.
100 (correction::compute_display_cols): Pass m_policy rather than
101 m_tabstop to cpp_display_width.
102 (correction::m_tabstop): Replace with...
103 (correction::m_policy): ...this.
104 (line_corrections::line_corrections): Pass in policy rather than
105 context.
106 (line_corrections::m_context): Replace with...
107 (line_corrections::m_policy): ...this.
108 (line_corrections::add_hint): Update to use m_policy rather than
109 m_context.
110 (line_corrections::add_hint): Likewise.
111 (layout::print_trailing_fixits): Likewise.
112 (selftest::test_display_widths): New.
113 (selftest::test_layout_x_offset_display_utf8): Update to use
114 policy rather than tabstop.
115 (selftest::test_one_liner_labels_utf8): Add test of escaping
116 source lines.
117 (selftest::test_diagnostic_show_locus_one_liner_utf8): Update to
118 use policy rather than tabstop.
119 (selftest::test_overlapped_fixit_printing): Likewise.
120 (selftest::test_overlapped_fixit_printing_utf8): Likewise.
121 (selftest::test_overlapped_fixit_printing_2): Likewise.
122 (selftest::test_tab_expansion): Likewise.
123 (selftest::test_escaping_bytes_1): New.
124 (selftest::test_escaping_bytes_2): New.
125 (selftest::diagnostic_show_locus_c_tests): Call the new tests.
126 * diagnostic.c (diagnostic_initialize): Initialize
127 context->escape_format.
128 (convert_column_unit): Update to use default character width policy.
129 (selftest::test_diagnostic_get_location_text): Likewise.
130 * diagnostic.h (enum diagnostics_escape_format): New enum.
131 (diagnostic_context::escape_format): New field.
132 * doc/invoke.texi (-fdiagnostics-escape-format=): New option.
133 (-fdiagnostics-format=): Add "escape-source" attribute to examples
134 of JSON output, and document it.
135 * input.c (location_compute_display_column): Pass in "policy"
136 rather than "tabstop", passing to
137 cpp_byte_column_to_display_column.
138 (selftest::test_cpp_utf8): Update to use cpp_char_column_policy.
139 * input.h (class cpp_char_column_policy): New forward decl.
140 (location_compute_display_column): Pass in "policy" rather than
141 "tabstop".
142 * opts.c (common_handle_option): Handle
143 OPT_fdiagnostics_escape_format_.
144 * selftest.c (temp_source_file::temp_source_file): New ctor
145 overload taking a size_t.
146 * selftest.h (temp_source_file::temp_source_file): Likewise.
147
148gcc/testsuite/ChangeLog:
149 * c-c++-common/diagnostic-format-json-1.c: Add regexp to consume
150 "escape-source" attribute.
151 * c-c++-common/diagnostic-format-json-2.c: Likewise.
152 * c-c++-common/diagnostic-format-json-3.c: Likewise.
153 * c-c++-common/diagnostic-format-json-4.c: Likewise, twice.
154 * c-c++-common/diagnostic-format-json-5.c: Likewise.
155 * gcc.dg/cpp/warn-normalized-4-bytes.c: New test.
156 * gcc.dg/cpp/warn-normalized-4-unicode.c: New test.
157 * gcc.dg/encoding-issues-bytes.c: New test.
158 * gcc.dg/encoding-issues-unicode.c: New test.
159 * gfortran.dg/diagnostic-format-json-1.F90: Add regexp to consume
160 "escape-source" attribute.
161 * gfortran.dg/diagnostic-format-json-2.F90: Likewise.
162 * gfortran.dg/diagnostic-format-json-3.F90: Likewise.
163
164libcpp/ChangeLog:
165 * charset.c (convert_escape): Use encoding_rich_location when
166 complaining about nonprintable unknown escape sequences.
167 (cpp_display_width_computation::::cpp_display_width_computation):
168 Pass in policy rather than tabstop.
169 (cpp_display_width_computation::process_next_codepoint): Add "out"
170 param and populate *out if non-NULL.
171 (cpp_display_width_computation::advance_display_cols): Pass NULL
172 to process_next_codepoint.
173 (cpp_byte_column_to_display_column): Pass in policy rather than
174 tabstop. Pass NULL to process_next_codepoint.
175 (cpp_display_column_to_byte_column): Pass in policy rather than
176 tabstop.
177 * errors.c (cpp_diagnostic_get_current_location): New function,
178 splitting out the logic from...
179 (cpp_diagnostic): ...here.
180 (cpp_warning_at): New function.
181 (cpp_pedwarning_at): New function.
182 * include/cpplib.h (cpp_warning_at): New decl for rich_location.
183 (cpp_pedwarning_at): Likewise.
184 (struct cpp_decoded_char): New.
185 (struct cpp_char_column_policy): New.
186 (cpp_display_width_computation::cpp_display_width_computation):
187 Replace "tabstop" param with "policy".
188 (cpp_display_width_computation::process_next_codepoint): Add "out"
189 param.
190 (cpp_display_width_computation::m_tabstop): Replace with...
191 (cpp_display_width_computation::m_policy): ...this.
192 (cpp_byte_column_to_display_column): Replace "tabstop" param with
193 "policy".
194 (cpp_display_width): Likewise.
195 (cpp_display_column_to_byte_column): Likewise.
196 * include/line-map.h (rich_location::escape_on_output_p): New.
197 (rich_location::set_escape_on_output): New.
198 (rich_location::m_escape_on_output): New.
199 * internal.h (cpp_diagnostic_get_current_location): New decl.
200 (class encoding_rich_location): New.
201 * lex.c (skip_whitespace): Use encoding_rich_location when
202 complaining about null characters.
203 (warn_about_normalization): Generate a source range when
204 complaining about improperly normalized tokens, rather than just a
205 point, and use encoding_rich_location so that the source code
206 is escaped on printing.
207 * line-map.c (rich_location::rich_location): Initialize
208 m_escape_on_output.
209
210Signed-off-by: David Malcolm <dmalcolm@redhat.com>
211
212CVE: CVE-2021-42574
213Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=bd5e882cf6e0def3dd1bc106075d59a303fe0d1e]
214Signed-off-by: Pgowda <pgowda.cve@gmail.com>
215
216---
217 gcc/c-family/c-lex.c | 6 +-
218 gcc/common.opt | 13 +
219 gcc/diagnostic-format-json.cc | 3 +
220 gcc/diagnostic-show-locus.c | 580 +++++++++++++++---
221 gcc/diagnostic.c | 10 +-
222 gcc/diagnostic.h | 18 +
223 gcc/doc/invoke.texi | 43 +-
224 gcc/input.c | 62 +-
225 gcc/input.h | 7 +-
226 gcc/opts.c | 4 +
227 gcc/selftest.c | 15 +
228 gcc/selftest.h | 2 +
229 .../c-c++-common/diagnostic-format-json-1.c | 1 +
230 .../c-c++-common/diagnostic-format-json-2.c | 1 +
231 .../c-c++-common/diagnostic-format-json-3.c | 1 +
232 .../c-c++-common/diagnostic-format-json-4.c | 2 +
233 .../c-c++-common/diagnostic-format-json-5.c | 1 +
234 .../gcc.dg/cpp/warn-normalized-4-bytes.c | 21 +
235 .../gcc.dg/cpp/warn-normalized-4-unicode.c | 19 +
236 gcc/testsuite/gcc.dg/encoding-issues-bytes.c | Bin 0 -> 595 bytes
237 .../gcc.dg/encoding-issues-unicode.c | Bin 0 -> 613 bytes
238 .../gfortran.dg/diagnostic-format-json-1.F90 | 1 +
239 .../gfortran.dg/diagnostic-format-json-2.F90 | 1 +
240 .../gfortran.dg/diagnostic-format-json-3.F90 | 1 +
241 libcpp/charset.c | 63 +-
242 libcpp/errors.c | 82 ++-
243 libcpp/include/cpplib.h | 76 ++-
244 libcpp/include/line-map.h | 13 +
245 libcpp/internal.h | 23 +
246 libcpp/lex.c | 38 +-
247 libcpp/line-map.c | 3 +-
248 31 files changed, 942 insertions(+), 168 deletions(-)
249 create mode 100644 gcc/testsuite/gcc.dg/cpp/warn-normalized-4-bytes.c
250 create mode 100644 gcc/testsuite/gcc.dg/cpp/warn-normalized-4-unicode.c
251 create mode 100644 gcc/testsuite/gcc.dg/encoding-issues-bytes.c
252 create mode 100644 gcc/testsuite/gcc.dg/encoding-issues-unicode.c
253
254diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
255--- a/gcc/c-family/c-lex.c 2020-07-22 23:35:17.296384022 -0700
256+++ b/gcc/c-family/c-lex.c 2021-12-25 01:30:50.669689023 -0800
257@@ -587,7 +587,11 @@ c_lex_with_flags (tree *value, location_
258 else if (ISGRAPH (c))
259 error_at (*loc, "stray %qc in program", (int) c);
260 else
261- error_at (*loc, "stray %<\\%o%> in program", (int) c);
262+ {
263+ rich_location rich_loc (line_table, *loc);
264+ rich_loc.set_escape_on_output (true);
265+ error_at (&rich_loc, "stray %<\\%o%> in program", (int) c);
266+ }
267 }
268 goto retry;
269
270diff --git a/gcc/common.opt b/gcc/common.opt
271--- a/gcc/common.opt 2021-12-25 01:29:12.915317374 -0800
272+++ b/gcc/common.opt 2021-12-25 01:30:50.669689023 -0800
273@@ -1337,6 +1337,10 @@ fdiagnostics-format=
274 Common Joined RejectNegative Enum(diagnostics_output_format)
275 -fdiagnostics-format=[text|json] Select output format.
276
277+fdiagnostics-escape-format=
278+Common Joined RejectNegative Enum(diagnostics_escape_format)
279+-fdiagnostics-escape-format=[unicode|bytes] Select how to escape non-printable-ASCII bytes in the source for diagnostics that suggest it.
280+
281 ; Required for these enum values.
282 SourceInclude
283 diagnostic.h
284@@ -1351,6 +1355,15 @@ EnumValue
285 Enum(diagnostics_column_unit) String(byte) Value(DIAGNOSTICS_COLUMN_UNIT_BYTE)
286
287 Enum
288+Name(diagnostics_escape_format) Type(int)
289+
290+EnumValue
291+Enum(diagnostics_escape_format) String(unicode) Value(DIAGNOSTICS_ESCAPE_FORMAT_UNICODE)
292+
293+EnumValue
294+Enum(diagnostics_escape_format) String(bytes) Value(DIAGNOSTICS_ESCAPE_FORMAT_BYTES)
295+
296+Enum
297 Name(diagnostics_output_format) Type(int)
298
299 EnumValue
300diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
301--- a/gcc/diagnostic.c 2021-12-25 01:29:12.915317374 -0800
302+++ b/gcc/diagnostic.c 2021-12-25 01:30:50.669689023 -0800
303@@ -223,6 +223,7 @@ diagnostic_initialize (diagnostic_contex
304 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
305 context->column_origin = 1;
306 context->tabstop = 8;
307+ context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
308 context->edit_context_ptr = NULL;
309 context->diagnostic_group_nesting_depth = 0;
310 context->diagnostic_group_emission_count = 0;
311@@ -2152,8 +2153,8 @@ test_diagnostic_get_location_text ()
312 const char *const content = "smile \xf0\x9f\x98\x82\n";
313 const int line_bytes = strlen (content) - 1;
314 const int def_tabstop = 8;
315- const int display_width = cpp_display_width (content, line_bytes,
316- def_tabstop);
317+ const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
318+ const int display_width = cpp_display_width (content, line_bytes, policy);
319 ASSERT_EQ (line_bytes - 2, display_width);
320 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
321 const char *const fname = tmp.get_filename ();
322diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
323--- a/gcc/diagnostic-format-json.cc 2021-12-25 01:29:12.915317374 -0800
324+++ b/gcc/diagnostic-format-json.cc 2021-12-25 01:30:50.669689023 -0800
325@@ -264,6 +264,9 @@ json_end_diagnostic (diagnostic_context
326 json::value *path_value = context->make_json_for_path (context, path);
327 diag_obj->set ("path", path_value);
328 }
329+
330+ diag_obj->set ("escape-source",
331+ new json::literal (richloc->escape_on_output_p ()));
332 }
333
334 /* No-op implementation of "begin_group_cb" for JSON output. */
335diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
336--- a/gcc/diagnostic.h 2021-12-25 01:29:12.919317307 -0800
337+++ b/gcc/diagnostic.h 2021-12-25 01:30:50.669689023 -0800
338@@ -38,6 +38,20 @@ enum diagnostics_column_unit
339 DIAGNOSTICS_COLUMN_UNIT_BYTE
340 };
341
342+/* An enum for controlling how to print non-ASCII characters/bytes when
343+ a diagnostic suggests escaping the source code on output. */
344+
345+enum diagnostics_escape_format
346+{
347+ /* Escape non-ASCII Unicode characters in the form <U+XXXX> and
348+ non-UTF-8 bytes in the form <XX>. */
349+ DIAGNOSTICS_ESCAPE_FORMAT_UNICODE,
350+
351+ /* Escape non-ASCII bytes in the form <XX> (thus showing the underlying
352+ encoding of non-ASCII Unicode characters). */
353+ DIAGNOSTICS_ESCAPE_FORMAT_BYTES
354+};
355+
356 /* Enum for overriding the standard output format. */
357
358 enum diagnostics_output_format
359@@ -303,6 +317,10 @@ struct diagnostic_context
360 /* The size of the tabstop for tab expansion. */
361 int tabstop;
362
363+ /* How should non-ASCII/non-printable bytes be escaped when
364+ a diagnostic suggests escaping the source code on output. */
365+ enum diagnostics_escape_format escape_format;
366+
367 /* If non-NULL, an edit_context to which fix-it hints should be
368 applied, for generating patches. */
369 edit_context *edit_context_ptr;
370diff --git a/gcc/diagnostic-show-locus.c b/gcc/diagnostic-show-locus.c
371--- a/gcc/diagnostic-show-locus.c 2021-12-25 01:29:12.919317307 -0800
372+++ b/gcc/diagnostic-show-locus.c 2021-12-25 01:30:50.673688956 -0800
373@@ -175,10 +175,26 @@ enum column_unit {
374 class exploc_with_display_col : public expanded_location
375 {
376 public:
377- exploc_with_display_col (const expanded_location &exploc, int tabstop)
378- : expanded_location (exploc),
379- m_display_col (location_compute_display_column (exploc, tabstop))
380- {}
381+ exploc_with_display_col (const expanded_location &exploc,
382+ const cpp_char_column_policy &policy,
383+ enum location_aspect aspect)
384+ : expanded_location (exploc),
385+ m_display_col (location_compute_display_column (exploc, policy))
386+ {
387+ if (exploc.column > 0)
388+ {
389+ /* m_display_col is now the final column of the byte.
390+ If escaping has happened, we may want the first column instead. */
391+ if (aspect != LOCATION_ASPECT_FINISH)
392+ {
393+ expanded_location prev_exploc (exploc);
394+ prev_exploc.column--;
395+ int prev_display_col
396+ = (location_compute_display_column (prev_exploc, policy));
397+ m_display_col = prev_display_col + 1;
398+ }
399+ }
400+ }
401
402 int m_display_col;
403 };
404@@ -313,6 +329,31 @@ test_line_span ()
405
406 #endif /* #if CHECKING_P */
407
408+/* A bundle of information containing how to print unicode
409+ characters and bytes when quoting source code.
410+
411+ Provides a unified place to support escaping some subset
412+ of characters to some format.
413+
414+ Extends char_column_policy; printing is split out to avoid
415+ libcpp having to know about pretty_printer. */
416+
417+struct char_display_policy : public cpp_char_column_policy
418+{
419+ public:
420+ char_display_policy (int tabstop,
421+ int (*width_cb) (cppchar_t c),
422+ void (*print_cb) (pretty_printer *pp,
423+ const cpp_decoded_char &cp))
424+ : cpp_char_column_policy (tabstop, width_cb),
425+ m_print_cb (print_cb)
426+ {
427+ }
428+
429+ void (*m_print_cb) (pretty_printer *pp,
430+ const cpp_decoded_char &cp);
431+};
432+
433 /* A class to control the overall layout when printing a diagnostic.
434
435 The layout is determined within the constructor.
436@@ -345,6 +386,8 @@ class layout
437
438 void print_line (linenum_type row);
439
440+ void on_bad_codepoint (const char *ptr, cppchar_t ch, size_t ch_sz);
441+
442 private:
443 bool will_show_line_p (linenum_type row) const;
444 void print_leading_fixits (linenum_type row);
445@@ -386,6 +429,7 @@ class layout
446 private:
447 diagnostic_context *m_context;
448 pretty_printer *m_pp;
449+ char_display_policy m_policy;
450 location_t m_primary_loc;
451 exploc_with_display_col m_exploc;
452 colorizer m_colorizer;
453@@ -398,6 +442,7 @@ class layout
454 auto_vec <line_span> m_line_spans;
455 int m_linenum_width;
456 int m_x_offset_display;
457+ bool m_escape_on_output;
458 };
459
460 /* Implementation of "class colorizer". */
461@@ -646,6 +691,11 @@ layout_range::intersects_line_p (linenum
462 /* Default for when we don't care what the tab expansion is set to. */
463 static const int def_tabstop = 8;
464
465+static cpp_char_column_policy def_policy ()
466+{
467+ return cpp_char_column_policy (8, cpp_wcwidth);
468+}
469+
470 /* Create some expanded locations for testing layout_range. The filename
471 member of the explocs is set to the empty string. This member will only be
472 inspected by the calls to location_compute_display_column() made from the
473@@ -662,10 +712,13 @@ make_range (int start_line, int start_co
474 = {"", start_line, start_col, NULL, false};
475 const expanded_location finish_exploc
476 = {"", end_line, end_col, NULL, false};
477- return layout_range (exploc_with_display_col (start_exploc, def_tabstop),
478- exploc_with_display_col (finish_exploc, def_tabstop),
479+ return layout_range (exploc_with_display_col (start_exploc, def_policy (),
480+ LOCATION_ASPECT_START),
481+ exploc_with_display_col (finish_exploc, def_policy (),
482+ LOCATION_ASPECT_FINISH),
483 SHOW_RANGE_WITHOUT_CARET,
484- exploc_with_display_col (start_exploc, def_tabstop),
485+ exploc_with_display_col (start_exploc, def_policy (),
486+ LOCATION_ASPECT_CARET),
487 0, NULL);
488 }
489
490@@ -950,6 +1003,164 @@ fixit_cmp (const void *p_a, const void *
491 return hint_a->get_start_loc () - hint_b->get_start_loc ();
492 }
493
494+/* Callbacks for use when not escaping the source. */
495+
496+/* The default callback for char_column_policy::m_width_cb is cpp_wcwidth. */
497+
498+/* Callback for char_display_policy::m_print_cb for printing source chars
499+ when not escaping the source. */
500+
501+static void
502+default_print_decoded_ch (pretty_printer *pp,
503+ const cpp_decoded_char &decoded_ch)
504+{
505+ for (const char *ptr = decoded_ch.m_start_byte;
506+ ptr != decoded_ch.m_next_byte; ptr++)
507+ {
508+ if (*ptr == '\0' || *ptr == '\r')
509+ {
510+ pp_space (pp);
511+ continue;
512+ }
513+
514+ pp_character (pp, *ptr);
515+ }
516+}
517+
518+/* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
519+
520+static const int width_per_escaped_byte = 4;
521+
522+/* Callback for char_column_policy::m_width_cb for determining the
523+ display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
524+
525+static int
526+escape_as_bytes_width (cppchar_t ch)
527+{
528+ if (ch < 0x80 && ISPRINT (ch))
529+ return cpp_wcwidth (ch);
530+ else
531+ {
532+ if (ch <= 0x7F) return 1 * width_per_escaped_byte;
533+ if (ch <= 0x7FF) return 2 * width_per_escaped_byte;
534+ if (ch <= 0xFFFF) return 3 * width_per_escaped_byte;
535+ return 4 * width_per_escaped_byte;
536+ }
537+}
538+
539+/* Callback for char_display_policy::m_print_cb for printing source chars
540+ when escaping with DIAGNOSTICS_ESCAPE_FORMAT_BYTES. */
541+
542+static void
543+escape_as_bytes_print (pretty_printer *pp,
544+ const cpp_decoded_char &decoded_ch)
545+{
546+ if (!decoded_ch.m_valid_ch)
547+ {
548+ for (const char *iter = decoded_ch.m_start_byte;
549+ iter != decoded_ch.m_next_byte; ++iter)
550+ {
551+ char buf[16];
552+ sprintf (buf, "<%02x>", (unsigned char)*iter);
553+ pp_string (pp, buf);
554+ }
555+ return;
556+ }
557+
558+ cppchar_t ch = decoded_ch.m_ch;
559+ if (ch < 0x80 && ISPRINT (ch))
560+ pp_character (pp, ch);
561+ else
562+ {
563+ for (const char *iter = decoded_ch.m_start_byte;
564+ iter < decoded_ch.m_next_byte; ++iter)
565+ {
566+ char buf[16];
567+ sprintf (buf, "<%02x>", (unsigned char)*iter);
568+ pp_string (pp, buf);
569+ }
570+ }
571+}
572+
573+/* Callbacks for use with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
574+
575+/* Callback for char_column_policy::m_width_cb for determining the
576+ display width when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
577+
578+static int
579+escape_as_unicode_width (cppchar_t ch)
580+{
581+ if (ch < 0x80 && ISPRINT (ch))
582+ return cpp_wcwidth (ch);
583+ else
584+ {
585+ // Width of "<U+%04x>"
586+ if (ch > 0xfffff)
587+ return 10;
588+ else if (ch > 0xffff)
589+ return 9;
590+ else
591+ return 8;
592+ }
593+}
594+
595+/* Callback for char_display_policy::m_print_cb for printing source chars
596+ when escaping with DIAGNOSTICS_ESCAPE_FORMAT_UNICODE. */
597+
598+static void
599+escape_as_unicode_print (pretty_printer *pp,
600+ const cpp_decoded_char &decoded_ch)
601+{
602+ if (!decoded_ch.m_valid_ch)
603+ {
604+ escape_as_bytes_print (pp, decoded_ch);
605+ return;
606+ }
607+
608+ cppchar_t ch = decoded_ch.m_ch;
609+ if (ch < 0x80 && ISPRINT (ch))
610+ pp_character (pp, ch);
611+ else
612+ {
613+ char buf[16];
614+ sprintf (buf, "<U+%04X>", ch);
615+ pp_string (pp, buf);
616+ }
617+}
618+
619+/* Populate a char_display_policy based on DC and RICHLOC. */
620+
621+static char_display_policy
622+make_policy (const diagnostic_context &dc,
623+ const rich_location &richloc)
624+{
625+ /* The default is to not escape non-ASCII bytes. */
626+ char_display_policy result
627+ (dc.tabstop, cpp_wcwidth, default_print_decoded_ch);
628+
629+ /* If the diagnostic suggests escaping non-ASCII bytes, then
630+ use policy from user-supplied options. */
631+ if (richloc.escape_on_output_p ())
632+ {
633+ result.m_undecoded_byte_width = width_per_escaped_byte;
634+ switch (dc.escape_format)
635+ {
636+ default:
637+ gcc_unreachable ();
638+ case DIAGNOSTICS_ESCAPE_FORMAT_UNICODE:
639+ result.m_width_cb = escape_as_unicode_width;
640+ result.m_print_cb = escape_as_unicode_print;
641+ break;
642+ case DIAGNOSTICS_ESCAPE_FORMAT_BYTES:
643+ result.m_width_cb = escape_as_bytes_width;
644+ result.m_print_cb = escape_as_bytes_print;
645+ break;
646+ }
647+ }
648+
649+ return result;
650+}
651+
652 /* Implementation of class layout. */
653
654 /* Constructor for class layout.
655@@ -966,8 +1177,10 @@ layout::layout (diagnostic_context * con
656 diagnostic_t diagnostic_kind)
657 : m_context (context),
658 m_pp (context->printer),
659+ m_policy (make_policy (*context, *richloc)),
660 m_primary_loc (richloc->get_range (0)->m_loc),
661- m_exploc (richloc->get_expanded_location (0), context->tabstop),
662+ m_exploc (richloc->get_expanded_location (0), m_policy,
663+ LOCATION_ASPECT_CARET),
664 m_colorizer (context, diagnostic_kind),
665 m_colorize_source_p (context->colorize_source_p),
666 m_show_labels_p (context->show_labels_p),
667@@ -977,7 +1190,8 @@ layout::layout (diagnostic_context * con
668 m_fixit_hints (richloc->get_num_fixit_hints ()),
669 m_line_spans (1 + richloc->get_num_locations ()),
670 m_linenum_width (0),
671- m_x_offset_display (0)
672+ m_x_offset_display (0),
673+ m_escape_on_output (richloc->escape_on_output_p ())
674 {
675 for (unsigned int idx = 0; idx < richloc->get_num_locations (); idx++)
676 {
677@@ -1063,10 +1277,13 @@ layout::maybe_add_location_range (const
678
679 /* Everything is now known to be in the correct source file,
680 but it may require further sanitization. */
681- layout_range ri (exploc_with_display_col (start, m_context->tabstop),
682- exploc_with_display_col (finish, m_context->tabstop),
683+ layout_range ri (exploc_with_display_col (start, m_policy,
684+ LOCATION_ASPECT_START),
685+ exploc_with_display_col (finish, m_policy,
686+ LOCATION_ASPECT_FINISH),
687 loc_range->m_range_display_kind,
688- exploc_with_display_col (caret, m_context->tabstop),
689+ exploc_with_display_col (caret, m_policy,
690+ LOCATION_ASPECT_CARET),
691 original_idx, loc_range->m_label);
692
693 /* If we have a range that finishes before it starts (perhaps
694@@ -1400,7 +1617,7 @@ layout::calculate_x_offset_display ()
695 = get_line_bytes_without_trailing_whitespace (line.get_buffer (),
696 line.length ());
697 int eol_display_column
698- = cpp_display_width (line.get_buffer (), line_bytes, m_context->tabstop);
699+ = cpp_display_width (line.get_buffer (), line_bytes, m_policy);
700 if (caret_display_column > eol_display_column
701 || !caret_display_column)
702 {
703@@ -1479,7 +1696,7 @@ layout::print_source_line (linenum_type
704 /* This object helps to keep track of which display column we are at, which is
705 necessary for computing the line bounds in display units, for doing
706 tab expansion, and for implementing m_x_offset_display. */
707- cpp_display_width_computation dw (line, line_bytes, m_context->tabstop);
708+ cpp_display_width_computation dw (line, line_bytes, m_policy);
709
710 /* Skip the first m_x_offset_display display columns. In case the leading
711 portion that will be skipped ends with a character with wcwidth > 1, then
712@@ -1527,7 +1744,8 @@ layout::print_source_line (linenum_type
713 tabs and replacing some control bytes with spaces as necessary. */
714 const char *c = dw.next_byte ();
715 const int start_disp_col = dw.display_cols_processed () + 1;
716- const int this_display_width = dw.process_next_codepoint ();
717+ cpp_decoded_char cp;
718+ const int this_display_width = dw.process_next_codepoint (&cp);
719 if (*c == '\t')
720 {
721 /* The returned display width is the number of spaces into which the
722@@ -1536,15 +1754,6 @@ layout::print_source_line (linenum_type
723 pp_space (m_pp);
724 continue;
725 }
726- if (*c == '\0' || *c == '\r')
727- {
728- /* cpp_wcwidth() promises to return 1 for all control bytes, and we
729- want to output these as a single space too, so this case is
730- actually the same as the '\t' case. */
731- gcc_assert (this_display_width == 1);
732- pp_space (m_pp);
733- continue;
734- }
735
736 /* We have a (possibly multibyte) character to output; update the line
737 bounds if it is not whitespace. */
738@@ -1556,7 +1765,8 @@ layout::print_source_line (linenum_type
739 }
740
741 /* Output the character. */
742- while (c != dw.next_byte ()) pp_character (m_pp, *c++);
743+ m_policy.m_print_cb (m_pp, cp);
744+ c = dw.next_byte ();
745 }
746 print_newline ();
747 return lbounds;
748@@ -1655,14 +1865,14 @@ layout::print_annotation_line (linenum_t
749 class line_label
750 {
751 public:
752- line_label (diagnostic_context *context, int state_idx, int column,
753+ line_label (const cpp_char_column_policy &policy,
754+ int state_idx, int column,
755 label_text text)
756 : m_state_idx (state_idx), m_column (column),
757 m_text (text), m_label_line (0), m_has_vbar (true)
758 {
759 const int bytes = strlen (text.m_buffer);
760- m_display_width
761- = cpp_display_width (text.m_buffer, bytes, context->tabstop);
762+ m_display_width = cpp_display_width (text.m_buffer, bytes, policy);
763 }
764
765 /* Sorting is primarily by column, then by state index. */
766@@ -1722,7 +1932,7 @@ layout::print_any_labels (linenum_type r
767 if (text.m_buffer == NULL)
768 continue;
769
770- labels.safe_push (line_label (m_context, i, disp_col, text));
771+ labels.safe_push (line_label (m_policy, i, disp_col, text));
772 }
773 }
774
775@@ -2002,7 +2212,7 @@ public:
776
777 /* Get the range of bytes or display columns that HINT would affect. */
778 static column_range
779-get_affected_range (diagnostic_context *context,
780+get_affected_range (const cpp_char_column_policy &policy,
781 const fixit_hint *hint, enum column_unit col_unit)
782 {
783 expanded_location exploc_start = expand_location (hint->get_start_loc ());
784@@ -2013,13 +2223,11 @@ get_affected_range (diagnostic_context *
785 int finish_column;
786 if (col_unit == CU_DISPLAY_COLS)
787 {
788- start_column
789- = location_compute_display_column (exploc_start, context->tabstop);
790+ start_column = location_compute_display_column (exploc_start, policy);
791 if (hint->insertion_p ())
792 finish_column = start_column - 1;
793 else
794- finish_column
795- = location_compute_display_column (exploc_finish, context->tabstop);
796+ finish_column = location_compute_display_column (exploc_finish, policy);
797 }
798 else
799 {
800@@ -2032,12 +2240,13 @@ get_affected_range (diagnostic_context *
801 /* Get the range of display columns that would be printed for HINT. */
802
803 static column_range
804-get_printed_columns (diagnostic_context *context, const fixit_hint *hint)
805+get_printed_columns (const cpp_char_column_policy &policy,
806+ const fixit_hint *hint)
807 {
808 expanded_location exploc = expand_location (hint->get_start_loc ());
809- int start_column = location_compute_display_column (exploc, context->tabstop);
810+ int start_column = location_compute_display_column (exploc, policy);
811 int hint_width = cpp_display_width (hint->get_string (), hint->get_length (),
812- context->tabstop);
813+ policy);
814 int final_hint_column = start_column + hint_width - 1;
815 if (hint->insertion_p ())
816 {
817@@ -2047,8 +2256,7 @@ get_printed_columns (diagnostic_context
818 {
819 exploc = expand_location (hint->get_next_loc ());
820 --exploc.column;
821- int finish_column
822- = location_compute_display_column (exploc, context->tabstop);
823+ int finish_column = location_compute_display_column (exploc, policy);
824 return column_range (start_column,
825 MAX (finish_column, final_hint_column));
826 }
827@@ -2066,13 +2274,13 @@ public:
828 column_range affected_columns,
829 column_range printed_columns,
830 const char *new_text, size_t new_text_len,
831- int tabstop)
832+ const cpp_char_column_policy &policy)
833 : m_affected_bytes (affected_bytes),
834 m_affected_columns (affected_columns),
835 m_printed_columns (printed_columns),
836 m_text (xstrdup (new_text)),
837 m_byte_length (new_text_len),
838- m_tabstop (tabstop),
839+ m_policy (policy),
840 m_alloc_sz (new_text_len + 1)
841 {
842 compute_display_cols ();
843@@ -2090,7 +2298,7 @@ public:
844
845 void compute_display_cols ()
846 {
847- m_display_cols = cpp_display_width (m_text, m_byte_length, m_tabstop);
848+ m_display_cols = cpp_display_width (m_text, m_byte_length, m_policy);
849 }
850
851 void overwrite (int dst_offset, const char_span &src_span)
852@@ -2118,7 +2326,7 @@ public:
853 char *m_text;
854 size_t m_byte_length; /* Not including null-terminator. */
855 int m_display_cols;
856- int m_tabstop;
857+ const cpp_char_column_policy &m_policy;
858 size_t m_alloc_sz;
859 };
860
861@@ -2154,15 +2362,16 @@ correction::ensure_terminated ()
862 class line_corrections
863 {
864 public:
865- line_corrections (diagnostic_context *context, const char *filename,
866+ line_corrections (const char_display_policy &policy,
867+ const char *filename,
868 linenum_type row)
869- : m_context (context), m_filename (filename), m_row (row)
870+ : m_policy (policy), m_filename (filename), m_row (row)
871 {}
872 ~line_corrections ();
873
874 void add_hint (const fixit_hint *hint);
875
876- diagnostic_context *m_context;
877+ const char_display_policy &m_policy;
878 const char *m_filename;
879 linenum_type m_row;
880 auto_vec <correction *> m_corrections;
881@@ -2208,10 +2417,10 @@ source_line::source_line (const char *fi
882 void
883 line_corrections::add_hint (const fixit_hint *hint)
884 {
885- column_range affected_bytes = get_affected_range (m_context, hint, CU_BYTES);
886- column_range affected_columns = get_affected_range (m_context, hint,
887+ column_range affected_bytes = get_affected_range (m_policy, hint, CU_BYTES);
888+ column_range affected_columns = get_affected_range (m_policy, hint,
889 CU_DISPLAY_COLS);
890- column_range printed_columns = get_printed_columns (m_context, hint);
891+ column_range printed_columns = get_printed_columns (m_policy, hint);
892
893 /* Potentially consolidate. */
894 if (!m_corrections.is_empty ())
895@@ -2280,7 +2489,7 @@ line_corrections::add_hint (const fixit_
896 printed_columns,
897 hint->get_string (),
898 hint->get_length (),
899- m_context->tabstop));
900+ m_policy));
901 }
902
903 /* If there are any fixit hints on source line ROW, print them.
904@@ -2294,7 +2503,7 @@ layout::print_trailing_fixits (linenum_t
905 {
906 /* Build a list of correction instances for the line,
907 potentially consolidating hints (for the sake of readability). */
908- line_corrections corrections (m_context, m_exploc.file, row);
909+ line_corrections corrections (m_policy, m_exploc.file, row);
910 for (unsigned int i = 0; i < m_fixit_hints.length (); i++)
911 {
912 const fixit_hint *hint = m_fixit_hints[i];
913@@ -2635,6 +2844,59 @@ namespace selftest {
914
915 /* Selftests for diagnostic_show_locus. */
916
917+/* Verify that cpp_display_width correctly handles escaping. */
918+
919+static void
920+test_display_widths ()
921+{
922+ gcc_rich_location richloc (UNKNOWN_LOCATION);
923+
924+ /* U+03C0 "GREEK SMALL LETTER PI". */
925+ const char *pi = "\xCF\x80";
926+ /* U+1F642 "SLIGHTLY SMILING FACE". */
927+ const char *emoji = "\xF0\x9F\x99\x82";
928+ /* Stray trailing byte of a UTF-8 character. */
929+ const char *stray = "\xBF";
930+ /* U+10FFFF. */
931+ const char *max_codepoint = "\xF4\x8F\xBF\xBF";
932+
933+ /* No escaping. */
934+ {
935+ test_diagnostic_context dc;
936+ char_display_policy policy (make_policy (dc, richloc));
937+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 1);
938+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 2);
939+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 1);
940+ /* Don't check width of U+10FFFF; it's in a private use plane. */
941+ }
942+
943+ richloc.set_escape_on_output (true);
944+
945+ {
946+ test_diagnostic_context dc;
947+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
948+ char_display_policy policy (make_policy (dc, richloc));
949+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
950+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 9);
951+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
952+ ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
953+ policy),
954+ strlen ("<U+10FFFF>"));
955+ }
956+
957+ {
958+ test_diagnostic_context dc;
959+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
960+ char_display_policy policy (make_policy (dc, richloc));
961+ ASSERT_EQ (cpp_display_width (pi, strlen (pi), policy), 8);
962+ ASSERT_EQ (cpp_display_width (emoji, strlen (emoji), policy), 16);
963+ ASSERT_EQ (cpp_display_width (stray, strlen (stray), policy), 4);
964+ ASSERT_EQ (cpp_display_width (max_codepoint, strlen (max_codepoint),
965+ policy),
966+ 16);
967+ }
968+}
969+
970 /* For precise tests of the layout, make clear where the source line will
971 start. test_left_margin sets the total byte count from the left side of the
972 screen to the start of source lines, after the line number and the separator,
973@@ -2704,10 +2966,10 @@ test_layout_x_offset_display_utf8 (const
974 char_span lspan = location_get_source_line (tmp.get_filename (), 1);
975 ASSERT_EQ (line_display_cols,
976 cpp_display_width (lspan.get_buffer (), lspan.length (),
977- def_tabstop));
978+ def_policy ()));
979 ASSERT_EQ (line_display_cols,
980 location_compute_display_column (expand_location (line_end),
981- def_tabstop));
982+ def_policy ()));
983 ASSERT_EQ (0, memcmp (lspan.get_buffer () + (emoji_col - 1),
984 "\xf0\x9f\x98\x82\xf0\x9f\x98\x82", 8));
985
986@@ -2855,12 +3117,13 @@ test_layout_x_offset_display_tab (const
987 ASSERT_EQ ('\t', *(lspan.get_buffer () + (tab_col - 1)));
988 for (int tabstop = 1; tabstop != num_tabstops; ++tabstop)
989 {
990+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
991 ASSERT_EQ (line_bytes + extra_width[tabstop],
992 cpp_display_width (lspan.get_buffer (), lspan.length (),
993- tabstop));
994+ policy));
995 ASSERT_EQ (line_bytes + extra_width[tabstop],
996 location_compute_display_column (expand_location (line_end),
997- tabstop));
998+ policy));
999 }
1000
1001 /* Check that the tab is expanded to the expected number of spaces. */
1002@@ -3992,6 +4255,43 @@ test_one_liner_labels_utf8 ()
1003 " bb\xf0\x9f\x98\x82\xf0\x9f\x98\x82\n",
1004 pp_formatted_text (dc.printer));
1005 }
1006+
1007+ /* Example of escaping the source lines. */
1008+ {
1009+ text_range_label label0 ("label 0\xf0\x9f\x98\x82");
1010+ text_range_label label1 ("label 1\xcf\x80");
1011+ text_range_label label2 ("label 2\xcf\x80");
1012+ gcc_rich_location richloc (foo, &label0);
1013+ richloc.add_range (bar, SHOW_RANGE_WITHOUT_CARET, &label1);
1014+ richloc.add_range (field, SHOW_RANGE_WITHOUT_CARET, &label2);
1015+ richloc.set_escape_on_output (true);
1016+
1017+ {
1018+ test_diagnostic_context dc;
1019+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
1020+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1021+ ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
1022+ " ^~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
1023+ " | | |\n"
1024+ " | | label 2\xcf\x80\n"
1025+ " | label 1\xcf\x80\n"
1026+ " label 0\xf0\x9f\x98\x82\n",
1027+ pp_formatted_text (dc.printer));
1028+ }
1029+ {
1030+ test_diagnostic_context dc;
1031+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
1032+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1033+ ASSERT_STREQ
1034+ (" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
1035+ " ^~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
1036+ " | | |\n"
1037+ " | | label 2\xcf\x80\n"
1038+ " | label 1\xcf\x80\n"
1039+ " label 0\xf0\x9f\x98\x82\n",
1040+ pp_formatted_text (dc.printer));
1041+ }
1042+ }
1043 }
1044
1045 /* Make sure that colorization codes don't interrupt a multibyte
1046@@ -4046,9 +4346,9 @@ test_diagnostic_show_locus_one_liner_utf
1047
1048 char_span lspan = location_get_source_line (tmp.get_filename (), 1);
1049 ASSERT_EQ (25, cpp_display_width (lspan.get_buffer (), lspan.length (),
1050- def_tabstop));
1051+ def_policy ()));
1052 ASSERT_EQ (25, location_compute_display_column (expand_location (line_end),
1053- def_tabstop));
1054+ def_policy ()));
1055
1056 test_one_liner_simple_caret_utf8 ();
1057 test_one_liner_caret_and_range_utf8 ();
1058@@ -4434,30 +4734,31 @@ test_overlapped_fixit_printing (const li
1059 pp_formatted_text (dc.printer));
1060
1061 /* Unit-test the line_corrections machinery. */
1062+ char_display_policy policy (make_policy (dc, richloc));
1063 ASSERT_EQ (3, richloc.get_num_fixit_hints ());
1064 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1065 ASSERT_EQ (column_range (12, 12),
1066- get_affected_range (&dc, hint_0, CU_BYTES));
1067+ get_affected_range (policy, hint_0, CU_BYTES));
1068 ASSERT_EQ (column_range (12, 12),
1069- get_affected_range (&dc, hint_0, CU_DISPLAY_COLS));
1070- ASSERT_EQ (column_range (12, 22), get_printed_columns (&dc, hint_0));
1071+ get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
1072+ ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
1073 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1074 ASSERT_EQ (column_range (18, 18),
1075- get_affected_range (&dc, hint_1, CU_BYTES));
1076+ get_affected_range (policy, hint_1, CU_BYTES));
1077 ASSERT_EQ (column_range (18, 18),
1078- get_affected_range (&dc, hint_1, CU_DISPLAY_COLS));
1079- ASSERT_EQ (column_range (18, 20), get_printed_columns (&dc, hint_1));
1080+ get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
1081+ ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
1082 const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
1083 ASSERT_EQ (column_range (29, 28),
1084- get_affected_range (&dc, hint_2, CU_BYTES));
1085+ get_affected_range (policy, hint_2, CU_BYTES));
1086 ASSERT_EQ (column_range (29, 28),
1087- get_affected_range (&dc, hint_2, CU_DISPLAY_COLS));
1088- ASSERT_EQ (column_range (29, 29), get_printed_columns (&dc, hint_2));
1089+ get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
1090+ ASSERT_EQ (column_range (29, 29), get_printed_columns (policy, hint_2));
1091
1092 /* Add each hint in turn to a line_corrections instance,
1093 and verify that they are consolidated into one correction instance
1094 as expected. */
1095- line_corrections lc (&dc, tmp.get_filename (), 1);
1096+ line_corrections lc (policy, tmp.get_filename (), 1);
1097
1098 /* The first replace hint by itself. */
1099 lc.add_hint (hint_0);
1100@@ -4649,30 +4950,31 @@ test_overlapped_fixit_printing_utf8 (con
1101 pp_formatted_text (dc.printer));
1102
1103 /* Unit-test the line_corrections machinery. */
1104+ char_display_policy policy (make_policy (dc, richloc));
1105 ASSERT_EQ (3, richloc.get_num_fixit_hints ());
1106 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1107 ASSERT_EQ (column_range (14, 14),
1108- get_affected_range (&dc, hint_0, CU_BYTES));
1109+ get_affected_range (policy, hint_0, CU_BYTES));
1110 ASSERT_EQ (column_range (12, 12),
1111- get_affected_range (&dc, hint_0, CU_DISPLAY_COLS));
1112- ASSERT_EQ (column_range (12, 22), get_printed_columns (&dc, hint_0));
1113+ get_affected_range (policy, hint_0, CU_DISPLAY_COLS));
1114+ ASSERT_EQ (column_range (12, 22), get_printed_columns (policy, hint_0));
1115 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1116 ASSERT_EQ (column_range (22, 22),
1117- get_affected_range (&dc, hint_1, CU_BYTES));
1118+ get_affected_range (policy, hint_1, CU_BYTES));
1119 ASSERT_EQ (column_range (18, 18),
1120- get_affected_range (&dc, hint_1, CU_DISPLAY_COLS));
1121- ASSERT_EQ (column_range (18, 20), get_printed_columns (&dc, hint_1));
1122+ get_affected_range (policy, hint_1, CU_DISPLAY_COLS));
1123+ ASSERT_EQ (column_range (18, 20), get_printed_columns (policy, hint_1));
1124 const fixit_hint *hint_2 = richloc.get_fixit_hint (2);
1125 ASSERT_EQ (column_range (35, 34),
1126- get_affected_range (&dc, hint_2, CU_BYTES));
1127+ get_affected_range (policy, hint_2, CU_BYTES));
1128 ASSERT_EQ (column_range (30, 29),
1129- get_affected_range (&dc, hint_2, CU_DISPLAY_COLS));
1130- ASSERT_EQ (column_range (30, 30), get_printed_columns (&dc, hint_2));
1131+ get_affected_range (policy, hint_2, CU_DISPLAY_COLS));
1132+ ASSERT_EQ (column_range (30, 30), get_printed_columns (policy, hint_2));
1133
1134 /* Add each hint in turn to a line_corrections instance,
1135 and verify that they are consolidated into one correction instance
1136 as expected. */
1137- line_corrections lc (&dc, tmp.get_filename (), 1);
1138+ line_corrections lc (policy, tmp.get_filename (), 1);
1139
1140 /* The first replace hint by itself. */
1141 lc.add_hint (hint_0);
1142@@ -4866,15 +5168,16 @@ test_overlapped_fixit_printing_2 (const
1143 richloc.add_fixit_insert_before (col_21, "}");
1144
1145 /* These fixits should be accepted; they can't be consolidated. */
1146+ char_display_policy policy (make_policy (dc, richloc));
1147 ASSERT_EQ (2, richloc.get_num_fixit_hints ());
1148 const fixit_hint *hint_0 = richloc.get_fixit_hint (0);
1149 ASSERT_EQ (column_range (23, 22),
1150- get_affected_range (&dc, hint_0, CU_BYTES));
1151- ASSERT_EQ (column_range (23, 23), get_printed_columns (&dc, hint_0));
1152+ get_affected_range (policy, hint_0, CU_BYTES));
1153+ ASSERT_EQ (column_range (23, 23), get_printed_columns (policy, hint_0));
1154 const fixit_hint *hint_1 = richloc.get_fixit_hint (1);
1155 ASSERT_EQ (column_range (21, 20),
1156- get_affected_range (&dc, hint_1, CU_BYTES));
1157- ASSERT_EQ (column_range (21, 21), get_printed_columns (&dc, hint_1));
1158+ get_affected_range (policy, hint_1, CU_BYTES));
1159+ ASSERT_EQ (column_range (21, 21), get_printed_columns (policy, hint_1));
1160
1161 /* Verify that they're printed correctly. */
1162 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1163@@ -5141,10 +5444,11 @@ test_tab_expansion (const line_table_cas
1164 ....................123 45678901234 56789012345 columns */
1165
1166 const int tabstop = 8;
1167+ cpp_char_column_policy policy (tabstop, cpp_wcwidth);
1168 const int first_non_ws_byte_col = 7;
1169 const int right_quote_byte_col = 15;
1170 const int last_byte_col = 25;
1171- ASSERT_EQ (35, cpp_display_width (content, last_byte_col, tabstop));
1172+ ASSERT_EQ (35, cpp_display_width (content, last_byte_col, policy));
1173
1174 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
1175 line_table_test ltt (case_);
1176@@ -5187,6 +5491,114 @@ test_tab_expansion (const line_table_cas
1177 }
1178 }
1179
1180+/* Verify that the escaping machinery can cope with a variety of different
1181+ invalid bytes. */
1182+
1183+static void
1184+test_escaping_bytes_1 (const line_table_case &case_)
1185+{
1186+ const char content[] = "before\0\1\2\3\r\x80\xff""after\n";
1187+ const size_t sz = sizeof (content);
1188+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
1189+ line_table_test ltt (case_);
1190+ const line_map_ordinary *ord_map = linemap_check_ordinary
1191+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
1192+ linemap_line_start (line_table, 1, 100);
1193+
1194+ location_t finish
1195+ = linemap_position_for_line_and_column (line_table, ord_map, 1,
1196+ strlen (content));
1197+
1198+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
1199+ return;
1200+
1201+ /* Locations of the NUL and \r bytes. */
1202+ location_t nul_loc
1203+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 7);
1204+ location_t r_loc
1205+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 11);
1206+ gcc_rich_location richloc (nul_loc);
1207+ richloc.add_range (r_loc);
1208+
1209+ {
1210+ test_diagnostic_context dc;
1211+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1212+ ASSERT_STREQ (" before \1\2\3 \x80\xff""after\n"
1213+ " ^ ~\n",
1214+ pp_formatted_text (dc.printer));
1215+ }
1216+ richloc.set_escape_on_output (true);
1217+ {
1218+ test_diagnostic_context dc;
1219+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
1220+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1221+ ASSERT_STREQ
1222+ (" before<U+0000><U+0001><U+0002><U+0003><U+000D><80><ff>after\n"
1223+ " ^~~~~~~~ ~~~~~~~~\n",
1224+ pp_formatted_text (dc.printer));
1225+ }
1226+ {
1227+ test_diagnostic_context dc;
1228+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
1229+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1230+ ASSERT_STREQ (" before<00><01><02><03><0d><80><ff>after\n"
1231+ " ^~~~ ~~~~\n",
1232+ pp_formatted_text (dc.printer));
1233+ }
1234+}
1235+
1236+/* As above, but verify that we handle the initial byte of a line
1237+ correctly. */
1238+
1239+static void
1240+test_escaping_bytes_2 (const line_table_case &case_)
1241+{
1242+ const char content[] = "\0after\n";
1243+ const size_t sz = sizeof (content);
1244+ temp_source_file tmp (SELFTEST_LOCATION, ".c", content, sz);
1245+ line_table_test ltt (case_);
1246+ const line_map_ordinary *ord_map = linemap_check_ordinary
1247+ (linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 0));
1248+ linemap_line_start (line_table, 1, 100);
1249+
1250+ location_t finish
1251+ = linemap_position_for_line_and_column (line_table, ord_map, 1,
1252+ strlen (content));
1253+
1254+ if (finish > LINE_MAP_MAX_LOCATION_WITH_COLS)
1255+ return;
1256+
1257+ /* Location of the NUL byte. */
1258+ location_t nul_loc
1259+ = linemap_position_for_line_and_column (line_table, ord_map, 1, 1);
1260+ gcc_rich_location richloc (nul_loc);
1261+
1262+ {
1263+ test_diagnostic_context dc;
1264+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1265+ ASSERT_STREQ (" after\n"
1266+ " ^\n",
1267+ pp_formatted_text (dc.printer));
1268+ }
1269+ richloc.set_escape_on_output (true);
1270+ {
1271+ test_diagnostic_context dc;
1272+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
1273+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1274+ ASSERT_STREQ (" <U+0000>after\n"
1275+ " ^~~~~~~~\n",
1276+ pp_formatted_text (dc.printer));
1277+ }
1278+ {
1279+ test_diagnostic_context dc;
1280+ dc.escape_format = DIAGNOSTICS_ESCAPE_FORMAT_BYTES;
1281+ diagnostic_show_locus (&dc, &richloc, DK_ERROR);
1282+ ASSERT_STREQ (" <00>after\n"
1283+ " ^~~~\n",
1284+ pp_formatted_text (dc.printer));
1285+ }
1286+}
1287+
1288 /* Verify that line numbers are correctly printed for the case of
1289 a multiline range in which the width of the line numbers changes
1290 (e.g. from "9" to "10"). */
1291@@ -5243,6 +5655,8 @@ diagnostic_show_locus_c_tests ()
1292 test_layout_range_for_single_line ();
1293 test_layout_range_for_multiple_lines ();
1294
1295+ test_display_widths ();
1296+
1297 for_each_line_table_case (test_layout_x_offset_display_utf8);
1298 for_each_line_table_case (test_layout_x_offset_display_tab);
1299
1300@@ -5263,6 +5677,8 @@ diagnostic_show_locus_c_tests ()
1301 for_each_line_table_case (test_fixit_replace_containing_newline);
1302 for_each_line_table_case (test_fixit_deletion_affecting_newline);
1303 for_each_line_table_case (test_tab_expansion);
1304+ for_each_line_table_case (test_escaping_bytes_1);
1305+ for_each_line_table_case (test_escaping_bytes_2);
1306
1307 test_line_numbers_multiline_range ();
1308 }
1309diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
1310--- a/gcc/doc/invoke.texi 2021-12-25 01:29:12.927317174 -0800
1311+++ b/gcc/doc/invoke.texi 2021-12-25 01:30:50.681688823 -0800
1312@@ -295,7 +295,8 @@ Objective-C and Objective-C++ Dialects}.
1313 -fdiagnostics-show-path-depths @gol
1314 -fno-show-column @gol
1315 -fdiagnostics-column-unit=@r{[}display@r{|}byte@r{]} @gol
1316--fdiagnostics-column-origin=@var{origin}}
1317+-fdiagnostics-column-origin=@var{origin} @gol
1318+-fdiagnostics-escape-format=@r{[}unicode@r{|}bytes@r{]}}
1319
1320 @item Warning Options
1321 @xref{Warning Options,,Options to Request or Suppress Warnings}.
1322@@ -4451,6 +4452,38 @@ first column. The default value of 1 co
1323 behavior and to the GNU style guide. Some utilities may perform better with an
1324 origin of 0; any non-negative value may be specified.
1325
1326+@item -fdiagnostics-escape-format=@var{FORMAT}
1327+@opindex fdiagnostics-escape-format
1328+When GCC prints pertinent source lines for a diagnostic it normally attempts
1329+to print the source bytes directly. However, some diagnostics relate to encoding
1330+issues in the source file, such as malformed UTF-8, or issues with Unicode
1331+normalization. These diagnostics are flagged so that GCC will escape bytes
1332+that are not printable ASCII when printing their pertinent source lines.
1333+
1334+This option controls how such bytes should be escaped.
1335+
1336+The default @var{FORMAT}, @samp{unicode} displays Unicode characters that
1337+are not printable ASCII in the form @samp{<U+XXXX>}, and bytes that do not
1338+correspond to a Unicode character validly-encoded in UTF-8-encoded will be
1339+displayed as hexadecimal in the form @samp{<XX>}.
1340+
1341+For example, a source line containing the string @samp{before} followed by the
1342+Unicode character U+03C0 (``GREEK SMALL LETTER PI'', with UTF-8 encoding
1343+0xCF 0x80) followed by the byte 0xBF (a stray UTF-8 trailing byte), followed by
1344+the string @samp{after} will be printed for such a diagnostic as:
1345+
1346+@smallexample
1347+ before<U+03C0><BF>after
1348+@end smallexample
1349+
1350+Setting @var{FORMAT} to @samp{bytes} will display all non-printable-ASCII bytes
1351+in the form @samp{<XX>}, thus showing the underlying encoding of non-ASCII
1352+Unicode characters. For the example above, the following will be printed:
1353+
1354+@smallexample
1355+ before<CF><80><BF>after
1356+@end smallexample
1357+
1358 @item -fdiagnostics-format=@var{FORMAT}
1359 @opindex fdiagnostics-format
1360 Select a different format for printing diagnostics.
1361@@ -4518,9 +4551,11 @@ might be printed in JSON form (after for
1362 @}
1363 @}
1364 ],
1365+ "escape-source": false,
1366 "message": "...this statement, but the latter is @dots{}"
1367 @}
1368 ]
1369+ "escape-source": false,
1370 "column-origin": 1,
1371 @},
1372 @dots{}
1373@@ -4607,6 +4642,7 @@ of the expression, which have labels. I
1374 "label": "T @{aka struct t@}"
1375 @}
1376 ],
1377+ "escape-source": false,
1378 "message": "invalid operands to binary + @dots{}"
1379 @}
1380 @end smallexample
1381@@ -4660,6 +4696,7 @@ might be printed in JSON form as:
1382 @}
1383 @}
1384 ],
1385+ "escape-source": false,
1386 "message": "\u2018struct s\u2019 has no member named @dots{}"
1387 @}
1388 @end smallexample
1389@@ -4717,6 +4754,10 @@ For example, the intraprocedural example
1390 ]
1391 @end smallexample
1392
1393+Diagnostics have a boolean attribute @code{escape-source}, hinting whether
1394+non-ASCII bytes should be escaped when printing the pertinent lines of
1395+source code (@code{true} for diagnostics involving source encoding issues).
1396+
1397 @end table
1398
1399 @node Warning Options
1400diff --git a/gcc/input.c b/gcc/input.c
1401--- a/gcc/input.c 2021-12-25 01:29:12.927317174 -0800
1402+++ b/gcc/input.c 2021-12-25 01:30:50.681688823 -0800
1403@@ -913,7 +913,8 @@ make_location (location_t caret, source_
1404 source line in order to calculate the display width. If that cannot be done
1405 for any reason, then returns the byte column as a fallback. */
1406 int
1407-location_compute_display_column (expanded_location exploc, int tabstop)
1408+location_compute_display_column (expanded_location exploc,
1409+ const cpp_char_column_policy &policy)
1410 {
1411 if (!(exploc.file && *exploc.file && exploc.line && exploc.column))
1412 return exploc.column;
1413@@ -921,7 +922,7 @@ location_compute_display_column (expande
1414 /* If line is NULL, this function returns exploc.column which is the
1415 desired fallback. */
1416 return cpp_byte_column_to_display_column (line.get_buffer (), line.length (),
1417- exploc.column, tabstop);
1418+ exploc.column, policy);
1419 }
1420
1421 /* Dump statistics to stderr about the memory usage of the line_table
1422@@ -3609,43 +3610,50 @@ test_line_offset_overflow ()
1423 void test_cpp_utf8 ()
1424 {
1425 const int def_tabstop = 8;
1426+ cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
1427+
1428 /* Verify that wcwidth of invalid UTF-8 or control bytes is 1. */
1429 {
1430- int w_bad = cpp_display_width ("\xf0!\x9f!\x98!\x82!", 8, def_tabstop);
1431+ int w_bad = cpp_display_width ("\xf0!\x9f!\x98!\x82!", 8, policy);
1432 ASSERT_EQ (8, w_bad);
1433- int w_ctrl = cpp_display_width ("\r\n\v\0\1", 5, def_tabstop);
1434+ int w_ctrl = cpp_display_width ("\r\n\v\0\1", 5, policy);
1435 ASSERT_EQ (5, w_ctrl);
1436 }
1437
1438 /* Verify that wcwidth of valid UTF-8 is as expected. */
1439 {
1440- const int w_pi = cpp_display_width ("\xcf\x80", 2, def_tabstop);
1441+ const int w_pi = cpp_display_width ("\xcf\x80", 2, policy);
1442 ASSERT_EQ (1, w_pi);
1443- const int w_emoji = cpp_display_width ("\xf0\x9f\x98\x82", 4, def_tabstop);
1444+ const int w_emoji = cpp_display_width ("\xf0\x9f\x98\x82", 4, policy);
1445 ASSERT_EQ (2, w_emoji);
1446 const int w_umlaut_precomposed = cpp_display_width ("\xc3\xbf", 2,
1447- def_tabstop);
1448+ policy);
1449 ASSERT_EQ (1, w_umlaut_precomposed);
1450 const int w_umlaut_combining = cpp_display_width ("y\xcc\x88", 3,
1451- def_tabstop);
1452+ policy);
1453 ASSERT_EQ (1, w_umlaut_combining);
1454- const int w_han = cpp_display_width ("\xe4\xb8\xba", 3, def_tabstop);
1455+ const int w_han = cpp_display_width ("\xe4\xb8\xba", 3, policy);
1456 ASSERT_EQ (2, w_han);
1457- const int w_ascii = cpp_display_width ("GCC", 3, def_tabstop);
1458+ const int w_ascii = cpp_display_width ("GCC", 3, policy);
1459 ASSERT_EQ (3, w_ascii);
1460 const int w_mixed = cpp_display_width ("\xcf\x80 = 3.14 \xf0\x9f\x98\x82"
1461 "\x9f! \xe4\xb8\xba y\xcc\x88",
1462- 24, def_tabstop);
1463+ 24, policy);
1464 ASSERT_EQ (18, w_mixed);
1465 }
1466
1467 /* Verify that display width properly expands tabs. */
1468 {
1469 const char *tstr = "\tabc\td";
1470- ASSERT_EQ (6, cpp_display_width (tstr, 6, 1));
1471- ASSERT_EQ (10, cpp_display_width (tstr, 6, 3));
1472- ASSERT_EQ (17, cpp_display_width (tstr, 6, 8));
1473- ASSERT_EQ (1, cpp_display_column_to_byte_column (tstr, 6, 7, 8));
1474+ ASSERT_EQ (6, cpp_display_width (tstr, 6,
1475+ cpp_char_column_policy (1, cpp_wcwidth)));
1476+ ASSERT_EQ (10, cpp_display_width (tstr, 6,
1477+ cpp_char_column_policy (3, cpp_wcwidth)));
1478+ ASSERT_EQ (17, cpp_display_width (tstr, 6,
1479+ cpp_char_column_policy (8, cpp_wcwidth)));
1480+ ASSERT_EQ (1,
1481+ cpp_display_column_to_byte_column
1482+ (tstr, 6, 7, cpp_char_column_policy (8, cpp_wcwidth)));
1483 }
1484
1485 /* Verify that cpp_byte_column_to_display_column can go past the end,
1486@@ -3658,13 +3666,13 @@ void test_cpp_utf8 ()
1487 /* 111122223456
1488 Byte columns. */
1489
1490- ASSERT_EQ (5, cpp_display_width (str, 6, def_tabstop));
1491+ ASSERT_EQ (5, cpp_display_width (str, 6, policy));
1492 ASSERT_EQ (105,
1493- cpp_byte_column_to_display_column (str, 6, 106, def_tabstop));
1494+ cpp_byte_column_to_display_column (str, 6, 106, policy));
1495 ASSERT_EQ (10000,
1496- cpp_byte_column_to_display_column (NULL, 0, 10000, def_tabstop));
1497+ cpp_byte_column_to_display_column (NULL, 0, 10000, policy));
1498 ASSERT_EQ (0,
1499- cpp_byte_column_to_display_column (NULL, 10000, 0, def_tabstop));
1500+ cpp_byte_column_to_display_column (NULL, 10000, 0, policy));
1501 }
1502
1503 /* Verify that cpp_display_column_to_byte_column can go past the end,
1504@@ -3678,25 +3686,25 @@ void test_cpp_utf8 ()
1505 /* 000000000000000000000000000000000111111
1506 111122223333444456666777788889999012345
1507 Byte columns. */
1508- ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 2, def_tabstop));
1509+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 2, policy));
1510 ASSERT_EQ (15,
1511- cpp_display_column_to_byte_column (str, 15, 11, def_tabstop));
1512+ cpp_display_column_to_byte_column (str, 15, 11, policy));
1513 ASSERT_EQ (115,
1514- cpp_display_column_to_byte_column (str, 15, 111, def_tabstop));
1515+ cpp_display_column_to_byte_column (str, 15, 111, policy));
1516 ASSERT_EQ (10000,
1517- cpp_display_column_to_byte_column (NULL, 0, 10000, def_tabstop));
1518+ cpp_display_column_to_byte_column (NULL, 0, 10000, policy));
1519 ASSERT_EQ (0,
1520- cpp_display_column_to_byte_column (NULL, 10000, 0, def_tabstop));
1521+ cpp_display_column_to_byte_column (NULL, 10000, 0, policy));
1522
1523 /* Verify that we do not interrupt a UTF-8 sequence. */
1524- ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 1, def_tabstop));
1525+ ASSERT_EQ (4, cpp_display_column_to_byte_column (str, 15, 1, policy));
1526
1527 for (int byte_col = 1; byte_col <= 15; ++byte_col)
1528 {
1529 const int disp_col
1530- = cpp_byte_column_to_display_column (str, 15, byte_col, def_tabstop);
1531+ = cpp_byte_column_to_display_column (str, 15, byte_col, policy);
1532 const int byte_col2
1533- = cpp_display_column_to_byte_column (str, 15, disp_col, def_tabstop);
1534+ = cpp_display_column_to_byte_column (str, 15, disp_col, policy);
1535
1536 /* If we ask for the display column in the middle of a UTF-8
1537 sequence, it will return the length of the partial sequence,
1538diff --git a/gcc/input.h b/gcc/input.h
1539--- a/gcc/input.h 2021-12-25 01:29:12.927317174 -0800
1540+++ b/gcc/input.h 2021-12-25 01:30:50.681688823 -0800
1541@@ -39,8 +39,11 @@ STATIC_ASSERT (BUILTINS_LOCATION < RESER
1542 extern bool is_location_from_builtin_token (location_t);
1543 extern expanded_location expand_location (location_t);
1544
1545-extern int location_compute_display_column (expanded_location exploc,
1546- int tabstop);
1547+class cpp_char_column_policy;
1548+
1549+extern int
1550+location_compute_display_column (expanded_location exploc,
1551+ const cpp_char_column_policy &policy);
1552
1553 /* A class capturing the bounds of a buffer, to allow for run-time
1554 bounds-checking in a checked build. */
1555diff --git a/gcc/opts.c b/gcc/opts.c
1556--- a/gcc/opts.c 2021-12-25 01:29:12.927317174 -0800
1557+++ b/gcc/opts.c 2021-12-25 01:30:50.681688823 -0800
1558@@ -2447,6 +2447,10 @@ common_handle_option (struct gcc_options
1559 dc->column_origin = value;
1560 break;
1561
1562+ case OPT_fdiagnostics_escape_format_:
1563+ dc->escape_format = (enum diagnostics_escape_format)value;
1564+ break;
1565+
1566 case OPT_fdiagnostics_show_cwe:
1567 dc->show_cwe = value;
1568 break;
1569diff --git a/gcc/selftest.c b/gcc/selftest.c
1570--- a/gcc/selftest.c 2020-07-22 23:35:17.820389797 -0700
1571+++ b/gcc/selftest.c 2021-12-25 01:30:50.681688823 -0800
1572@@ -193,6 +193,21 @@ temp_source_file::temp_source_file (cons
1573 fclose (out);
1574 }
1575
1576+/* As above, but with a size, to allow for NUL bytes in CONTENT. */
1577+
1578+temp_source_file::temp_source_file (const location &loc,
1579+ const char *suffix,
1580+ const char *content,
1581+ size_t sz)
1582+: named_temp_file (suffix)
1583+{
1584+ FILE *out = fopen (get_filename (), "w");
1585+ if (!out)
1586+ fail_formatted (loc, "unable to open tempfile: %s", get_filename ());
1587+ fwrite (content, sz, 1, out);
1588+ fclose (out);
1589+}
1590+
1591 /* Avoid introducing locale-specific differences in the results
1592 by hardcoding open_quote and close_quote. */
1593
1594diff --git a/gcc/selftest.h b/gcc/selftest.h
1595--- a/gcc/selftest.h 2020-07-22 23:35:17.820389797 -0700
1596+++ b/gcc/selftest.h 2021-12-25 01:30:50.681688823 -0800
1597@@ -112,6 +112,8 @@ class temp_source_file : public named_te
1598 public:
1599 temp_source_file (const location &loc, const char *suffix,
1600 const char *content);
1601+ temp_source_file (const location &loc, const char *suffix,
1602+ const char *content, size_t sz);
1603 };
1604
1605 /* RAII-style class for avoiding introducing locale-specific differences
1606diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c
1607--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c 2021-12-25 01:29:12.927317174 -0800
1608+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-1.c 2021-12-25 01:30:50.681688823 -0800
1609@@ -9,6 +9,7 @@
1610
1611 /* { dg-regexp "\"kind\": \"error\"" } */
1612 /* { dg-regexp "\"column-origin\": 1" } */
1613+/* { dg-regexp "\"escape-source\": false" } */
1614 /* { dg-regexp "\"message\": \"#error message\"" } */
1615
1616 /* { dg-regexp "\"caret\": \{" } */
1617diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c
1618--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c 2021-12-25 01:29:12.927317174 -0800
1619+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-2.c 2021-12-25 01:30:50.681688823 -0800
1620@@ -9,6 +9,7 @@
1621
1622 /* { dg-regexp "\"kind\": \"warning\"" } */
1623 /* { dg-regexp "\"column-origin\": 1" } */
1624+/* { dg-regexp "\"escape-source\": false" } */
1625 /* { dg-regexp "\"message\": \"#warning message\"" } */
1626 /* { dg-regexp "\"option\": \"-Wcpp\"" } */
1627 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
1628diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c
1629--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c 2021-12-25 01:29:12.927317174 -0800
1630+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-3.c 2021-12-25 01:30:50.681688823 -0800
1631@@ -9,6 +9,7 @@
1632
1633 /* { dg-regexp "\"kind\": \"error\"" } */
1634 /* { dg-regexp "\"column-origin\": 1" } */
1635+/* { dg-regexp "\"escape-source\": false" } */
1636 /* { dg-regexp "\"message\": \"#warning message\"" } */
1637 /* { dg-regexp "\"option\": \"-Werror=cpp\"" } */
1638 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wcpp\"" } */
1639diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c
1640--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c 2021-12-25 01:29:12.927317174 -0800
1641+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-4.c 2021-12-25 01:30:50.681688823 -0800
1642@@ -19,6 +19,7 @@ int test (void)
1643
1644 /* { dg-regexp "\"kind\": \"note\"" } */
1645 /* { dg-regexp "\"message\": \"...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'\"" } */
1646+/* { dg-regexp "\"escape-source\": false" } */
1647
1648 /* { dg-regexp "\"caret\": \{" } */
1649 /* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-4.c\"" } */
1650@@ -39,6 +40,7 @@ int test (void)
1651 /* { dg-regexp "\"kind\": \"warning\"" } */
1652 /* { dg-regexp "\"column-origin\": 1" } */
1653 /* { dg-regexp "\"message\": \"this 'if' clause does not guard...\"" } */
1654+/* { dg-regexp "\"escape-source\": false" } */
1655 /* { dg-regexp "\"option\": \"-Wmisleading-indentation\"" } */
1656 /* { dg-regexp "\"option_url\": \"https:\[^\n\r\"\]*#index-Wmisleading-indentation\"" } */
1657
1658diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c
1659--- a/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c 2021-12-25 01:29:12.927317174 -0800
1660+++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-5.c 2021-12-25 01:30:50.681688823 -0800
1661@@ -14,6 +14,7 @@ int test (struct s *ptr)
1662
1663 /* { dg-regexp "\"kind\": \"error\"" } */
1664 /* { dg-regexp "\"column-origin\": 1" } */
1665+/* { dg-regexp "\"escape-source\": false" } */
1666 /* { dg-regexp "\"message\": \".*\"" } */
1667
1668 /* Verify fix-it hints. */
1669diff --git a/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-bytes.c b/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-bytes.c
1670--- a/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-bytes.c 1969-12-31 16:00:00.000000000 -0800
1671+++ b/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-bytes.c 2021-12-25 01:30:50.681688823 -0800
1672@@ -0,0 +1,21 @@
1673+// { dg-do preprocess }
1674+// { dg-options "-std=gnu99 -Werror=normalized=nfc -fdiagnostics-show-caret -fdiagnostics-escape-format=bytes" }
1675+/* { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 } */
1676+
1677+/* འ= U+0F43 TIBETAN LETTER GHA, which has decomposition "0F42 0FB7" i.e.
1678+ U+0F42 TIBETAN LETTER GA: à½
1679+ U+0FB7 TIBETAN SUBJOINED LETTER HA: ྷ
1680+
1681+ The UTF-8 encoding of U+0F43 TIBETAN LETTER GHA is: E0 BD 83. */
1682+
1683+foo before_\u0F43_after bar // { dg-error "`before_.U00000f43_after' is not in NFC .-Werror=normalized=." }
1684+/* { dg-begin-multiline-output "" }
1685+ foo before_\u0F43_after bar
1686+ ^~~~~~~~~~~~~~~~~~~
1687+ { dg-end-multiline-output "" } */
1688+
1689+foo before_à½_after bar // { dg-error "`before_.U00000f43_after' is not in NFC .-Werror=normalized=." }
1690+/* { dg-begin-multiline-output "" }
1691+ foo before_<e0><bd><83>_after bar
1692+ ^~~~~~~~~~~~~~~~~~~~~~~~~
1693+ { dg-end-multiline-output "" } */
1694diff --git a/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-unicode.c b/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-unicode.c
1695--- a/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-unicode.c 1969-12-31 16:00:00.000000000 -0800
1696+++ b/gcc/testsuite/gcc.dg/cpp/warn-normalized-4-unicode.c 2021-12-25 01:30:50.681688823 -0800
1697@@ -0,0 +1,19 @@
1698+// { dg-do preprocess }
1699+// { dg-options "-std=gnu99 -Werror=normalized=nfc -fdiagnostics-show-caret -fdiagnostics-escape-format=unicode" }
1700+/* { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 } */
1701+
1702+/* འ= U+0F43 TIBETAN LETTER GHA, which has decomposition "0F42 0FB7" i.e.
1703+ U+0F42 TIBETAN LETTER GA: à½
1704+ U+0FB7 TIBETAN SUBJOINED LETTER HA: ྷ */
1705+
1706+foo before_\u0F43_after bar // { dg-error "`before_.U00000f43_after' is not in NFC .-Werror=normalized=." }
1707+/* { dg-begin-multiline-output "" }
1708+ foo before_\u0F43_after bar
1709+ ^~~~~~~~~~~~~~~~~~~
1710+ { dg-end-multiline-output "" } */
1711+
1712+foo before_à½_after bar // { dg-error "`before_.U00000f43_after' is not in NFC .-Werror=normalized=." }
1713+/* { dg-begin-multiline-output "" }
1714+ foo before_<U+0F43>_after bar
1715+ ^~~~~~~~~~~~~~~~~~~~~
1716+ { dg-end-multiline-output "" } */
1717diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90
1718--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 2021-12-25 01:29:12.931317107 -0800
1719+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-1.F90 2021-12-25 01:30:50.681688823 -0800
1720@@ -9,6 +9,7 @@
1721
1722 ! { dg-regexp "\"kind\": \"error\"" }
1723 ! { dg-regexp "\"column-origin\": 1" }
1724+! { dg-regexp "\"escape-source\": false" }
1725 ! { dg-regexp "\"message\": \"#error message\"" }
1726
1727 ! { dg-regexp "\"caret\": \{" }
1728diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90
1729--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 2021-12-25 01:29:12.931317107 -0800
1730+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-2.F90 2021-12-25 01:30:50.681688823 -0800
1731@@ -9,6 +9,7 @@
1732
1733 ! { dg-regexp "\"kind\": \"warning\"" }
1734 ! { dg-regexp "\"column-origin\": 1" }
1735+! { dg-regexp "\"escape-source\": false" }
1736 ! { dg-regexp "\"message\": \"#warning message\"" }
1737 ! { dg-regexp "\"option\": \"-Wcpp\"" }
1738 ! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
1739diff --git a/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 b/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90
1740--- a/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 2021-12-25 01:29:12.931317107 -0800
1741+++ b/gcc/testsuite/gfortran.dg/diagnostic-format-json-3.F90 2021-12-25 01:30:50.681688823 -0800
1742@@ -9,6 +9,7 @@
1743
1744 ! { dg-regexp "\"kind\": \"error\"" }
1745 ! { dg-regexp "\"column-origin\": 1" }
1746+! { dg-regexp "\"escape-source\": false" }
1747 ! { dg-regexp "\"message\": \"#warning message\"" }
1748 ! { dg-regexp "\"option\": \"-Werror=cpp\"" }
1749 ! { dg-regexp "\"option_url\": \"\[^\n\r\"\]*#index-Wcpp\"" }
1750diff --git a/libcpp/charset.c b/libcpp/charset.c
1751--- a/libcpp/charset.c 2021-12-25 01:29:12.931317107 -0800
1752+++ b/libcpp/charset.c 2021-12-25 01:30:50.681688823 -0800
1753@@ -1549,12 +1549,14 @@ convert_escape (cpp_reader *pfile, const
1754 "unknown escape sequence: '\\%c'", (int) c);
1755 else
1756 {
1757+ encoding_rich_location rich_loc (pfile);
1758+
1759 /* diagnostic.c does not support "%03o". When it does, this
1760 code can use %03o directly in the diagnostic again. */
1761 char buf[32];
1762 sprintf(buf, "%03o", (int) c);
1763- cpp_error (pfile, CPP_DL_PEDWARN,
1764- "unknown escape sequence: '\\%s'", buf);
1765+ cpp_error_at (pfile, CPP_DL_PEDWARN, &rich_loc,
1766+ "unknown escape sequence: '\\%s'", buf);
1767 }
1768 }
1769
1770@@ -2277,14 +2279,16 @@ cpp_string_location_reader::get_next ()
1771 }
1772
1773 cpp_display_width_computation::
1774-cpp_display_width_computation (const char *data, int data_length, int tabstop) :
1775+cpp_display_width_computation (const char *data, int data_length,
1776+ const cpp_char_column_policy &policy) :
1777 m_begin (data),
1778 m_next (m_begin),
1779 m_bytes_left (data_length),
1780- m_tabstop (tabstop),
1781+ m_policy (policy),
1782 m_display_cols (0)
1783 {
1784- gcc_assert (m_tabstop > 0);
1785+ gcc_assert (policy.m_tabstop > 0);
1786+ gcc_assert (policy.m_width_cb);
1787 }
1788
1789
1790@@ -2296,19 +2300,28 @@ cpp_display_width_computation (const cha
1791 point to a valid UTF-8-encoded sequence, then it will be treated as a single
1792 byte with display width 1. m_cur_display_col is the current display column,
1793 relative to which tab stops should be expanded. Returns the display width of
1794- the codepoint just processed. */
1795+ the codepoint just processed.
1796+ If OUT is non-NULL, it is populated. */
1797
1798 int
1799-cpp_display_width_computation::process_next_codepoint ()
1800+cpp_display_width_computation::process_next_codepoint (cpp_decoded_char *out)
1801 {
1802 cppchar_t c;
1803 int next_width;
1804
1805+ if (out)
1806+ out->m_start_byte = m_next;
1807+
1808 if (*m_next == '\t')
1809 {
1810 ++m_next;
1811 --m_bytes_left;
1812- next_width = m_tabstop - (m_display_cols % m_tabstop);
1813+ next_width = m_policy.m_tabstop - (m_display_cols % m_policy.m_tabstop);
1814+ if (out)
1815+ {
1816+ out->m_ch = '\t';
1817+ out->m_valid_ch = true;
1818+ }
1819 }
1820 else if (one_utf8_to_cppchar ((const uchar **) &m_next, &m_bytes_left, &c)
1821 != 0)
1822@@ -2318,14 +2331,24 @@ cpp_display_width_computation::process_n
1823 of one. */
1824 ++m_next;
1825 --m_bytes_left;
1826- next_width = 1;
1827+ next_width = m_policy.m_undecoded_byte_width;
1828+ if (out)
1829+ out->m_valid_ch = false;
1830 }
1831 else
1832 {
1833 /* one_utf8_to_cppchar() has updated m_next and m_bytes_left for us. */
1834- next_width = cpp_wcwidth (c);
1835+ next_width = m_policy.m_width_cb (c);
1836+ if (out)
1837+ {
1838+ out->m_ch = c;
1839+ out->m_valid_ch = true;
1840+ }
1841 }
1842
1843+ if (out)
1844+ out->m_next_byte = m_next;
1845+
1846 m_display_cols += next_width;
1847 return next_width;
1848 }
1849@@ -2341,7 +2364,7 @@ cpp_display_width_computation::advance_d
1850 const int start = m_display_cols;
1851 const int target = start + n;
1852 while (m_display_cols < target && !done ())
1853- process_next_codepoint ();
1854+ process_next_codepoint (NULL);
1855 return m_display_cols - start;
1856 }
1857
1858@@ -2349,29 +2372,33 @@ cpp_display_width_computation::advance_d
1859 how many display columns are occupied by the first COLUMN bytes. COLUMN
1860 may exceed DATA_LENGTH, in which case the phantom bytes at the end are
1861 treated as if they have display width 1. Tabs are expanded to the next tab
1862- stop, relative to the start of DATA. */
1863+ stop, relative to the start of DATA, and non-printable-ASCII characters
1864+ will be escaped as per POLICY. */
1865
1866 int
1867 cpp_byte_column_to_display_column (const char *data, int data_length,
1868- int column, int tabstop)
1869+ int column,
1870+ const cpp_char_column_policy &policy)
1871 {
1872 const int offset = MAX (0, column - data_length);
1873- cpp_display_width_computation dw (data, column - offset, tabstop);
1874+ cpp_display_width_computation dw (data, column - offset, policy);
1875 while (!dw.done ())
1876- dw.process_next_codepoint ();
1877+ dw.process_next_codepoint (NULL);
1878 return dw.display_cols_processed () + offset;
1879 }
1880
1881 /* For the string of length DATA_LENGTH bytes that begins at DATA, compute
1882 the least number of bytes that will result in at least DISPLAY_COL display
1883 columns. The return value may exceed DATA_LENGTH if the entire string does
1884- not occupy enough display columns. */
1885+ not occupy enough display columns. Non-printable-ASCII characters
1886+ will be escaped as per POLICY. */
1887
1888 int
1889 cpp_display_column_to_byte_column (const char *data, int data_length,
1890- int display_col, int tabstop)
1891+ int display_col,
1892+ const cpp_char_column_policy &policy)
1893 {
1894- cpp_display_width_computation dw (data, data_length, tabstop);
1895+ cpp_display_width_computation dw (data, data_length, policy);
1896 const int avail_display = dw.advance_display_cols (display_col);
1897 return dw.bytes_processed () + MAX (0, display_col - avail_display);
1898 }
1899diff --git a/libcpp/errors.c b/libcpp/errors.c
1900--- a/libcpp/errors.c 2020-07-22 23:35:18.712399623 -0700
1901+++ b/libcpp/errors.c 2021-12-25 01:30:50.681688823 -0800
1902@@ -27,6 +27,31 @@ along with this program; see the file CO
1903 #include "cpplib.h"
1904 #include "internal.h"
1905
1906+/* Get a location_t for the current location in PFILE,
1907+ generally that of the previously lexed token. */
1908+
1909+location_t
1910+cpp_diagnostic_get_current_location (cpp_reader *pfile)
1911+{
1912+ if (CPP_OPTION (pfile, traditional))
1913+ {
1914+ if (pfile->state.in_directive)
1915+ return pfile->directive_line;
1916+ else
1917+ return pfile->line_table->highest_line;
1918+ }
1919+ /* We don't want to refer to a token before the beginning of the
1920+ current run -- that is invalid. */
1921+ else if (pfile->cur_token == pfile->cur_run->base)
1922+ {
1923+ return 0;
1924+ }
1925+ else
1926+ {
1927+ return pfile->cur_token[-1].src_loc;
1928+ }
1929+}
1930+
1931 /* Print a diagnostic at the given location. */
1932
1933 ATTRIBUTE_FPTR_PRINTF(5,0)
1934@@ -52,25 +77,7 @@ cpp_diagnostic (cpp_reader * pfile, enum
1935 enum cpp_warning_reason reason,
1936 const char *msgid, va_list *ap)
1937 {
1938- location_t src_loc;
1939-
1940- if (CPP_OPTION (pfile, traditional))
1941- {
1942- if (pfile->state.in_directive)
1943- src_loc = pfile->directive_line;
1944- else
1945- src_loc = pfile->line_table->highest_line;
1946- }
1947- /* We don't want to refer to a token before the beginning of the
1948- current run -- that is invalid. */
1949- else if (pfile->cur_token == pfile->cur_run->base)
1950- {
1951- src_loc = 0;
1952- }
1953- else
1954- {
1955- src_loc = pfile->cur_token[-1].src_loc;
1956- }
1957+ location_t src_loc = cpp_diagnostic_get_current_location (pfile);
1958 rich_location richloc (pfile->line_table, src_loc);
1959 return cpp_diagnostic_at (pfile, level, reason, &richloc, msgid, ap);
1960 }
1961@@ -142,6 +149,43 @@ cpp_warning_syshdr (cpp_reader * pfile,
1962
1963 va_end (ap);
1964 return ret;
1965+}
1966+
1967+/* As cpp_warning above, but use RICHLOC as the location of the diagnostic. */
1968+
1969+bool cpp_warning_at (cpp_reader *pfile, enum cpp_warning_reason reason,
1970+ rich_location *richloc, const char *msgid, ...)
1971+{
1972+ va_list ap;
1973+ bool ret;
1974+
1975+ va_start (ap, msgid);
1976+
1977+ ret = cpp_diagnostic_at (pfile, CPP_DL_WARNING, reason, richloc,
1978+ msgid, &ap);
1979+
1980+ va_end (ap);
1981+ return ret;
1982+
1983+}
1984+
1985+/* As cpp_pedwarning above, but use RICHLOC as the location of the
1986+ diagnostic. */
1987+
1988+bool
1989+cpp_pedwarning_at (cpp_reader * pfile, enum cpp_warning_reason reason,
1990+ rich_location *richloc, const char *msgid, ...)
1991+{
1992+ va_list ap;
1993+ bool ret;
1994+
1995+ va_start (ap, msgid);
1996+
1997+ ret = cpp_diagnostic_at (pfile, CPP_DL_PEDWARN, reason, richloc,
1998+ msgid, &ap);
1999+
2000+ va_end (ap);
2001+ return ret;
2002 }
2003
2004 /* Print a diagnostic at a specific location. */
2005diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
2006--- a/libcpp/include/cpplib.h 2021-12-25 01:29:12.931317107 -0800
2007+++ b/libcpp/include/cpplib.h 2021-12-25 01:30:50.685688757 -0800
2008@@ -1176,6 +1176,14 @@ extern bool cpp_warning_syshdr (cpp_read
2009 const char *msgid, ...)
2010 ATTRIBUTE_PRINTF_3;
2011
2012+/* As their counterparts above, but use RICHLOC. */
2013+extern bool cpp_warning_at (cpp_reader *, enum cpp_warning_reason,
2014+ rich_location *richloc, const char *msgid, ...)
2015+ ATTRIBUTE_PRINTF_4;
2016+extern bool cpp_pedwarning_at (cpp_reader *, enum cpp_warning_reason,
2017+ rich_location *richloc, const char *msgid, ...)
2018+ ATTRIBUTE_PRINTF_4;
2019+
2020 /* Output a diagnostic with "MSGID: " preceding the
2021 error string of errno. No location is printed. */
2022 extern bool cpp_errno (cpp_reader *, enum cpp_diagnostic_level,
2023@@ -1320,42 +1328,95 @@ extern const char * cpp_get_userdef_suff
2024
2025 /* In charset.c */
2026
2027+/* The result of attempting to decode a run of UTF-8 bytes. */
2028+
2029+struct cpp_decoded_char
2030+{
2031+ const char *m_start_byte;
2032+ const char *m_next_byte;
2033+
2034+ bool m_valid_ch;
2035+ cppchar_t m_ch;
2036+};
2037+
2038+/* Information for mapping between code points and display columns.
2039+
2040+ This is a tabstop value, along with a callback for getting the
2041+ widths of characters. Normally this callback is cpp_wcwidth, but we
2042+ support other schemes for escaping non-ASCII unicode as a series of
2043+ ASCII chars when printing the user's source code in diagnostic-show-locus.c
2044+
2045+ For example, consider:
2046+ - the Unicode character U+03C0 "GREEK SMALL LETTER PI" (UTF-8: 0xCF 0x80)
2047+ - the Unicode character U+1F642 "SLIGHTLY SMILING FACE"
2048+ (UTF-8: 0xF0 0x9F 0x99 0x82)
2049+ - the byte 0xBF (a stray trailing byte of a UTF-8 character)
2050+ Normally U+03C0 would occupy one display column, U+1F642
2051+ would occupy two display columns, and the stray byte would be
2052+ printed verbatim as one display column.
2053+
2054+ However when escaping them as unicode code points as "<U+03C0>"
2055+ and "<U+1F642>" they occupy 8 and 9 display columns respectively,
2056+ and when escaping them as bytes as "<CF><80>" and "<F0><9F><99><82>"
2057+ they occupy 8 and 16 display columns respectively. In both cases
2058+ the stray byte is escaped to <BF> as 4 display columns. */
2059+
2060+struct cpp_char_column_policy
2061+{
2062+ cpp_char_column_policy (int tabstop,
2063+ int (*width_cb) (cppchar_t c))
2064+ : m_tabstop (tabstop),
2065+ m_undecoded_byte_width (1),
2066+ m_width_cb (width_cb)
2067+ {}
2068+
2069+ int m_tabstop;
2070+ /* Width in display columns of a stray byte that isn't decodable
2071+ as UTF-8. */
2072+ int m_undecoded_byte_width;
2073+ int (*m_width_cb) (cppchar_t c);
2074+};
2075+
2076 /* A class to manage the state while converting a UTF-8 sequence to cppchar_t
2077 and computing the display width one character at a time. */
2078 class cpp_display_width_computation {
2079 public:
2080 cpp_display_width_computation (const char *data, int data_length,
2081- int tabstop);
2082+ const cpp_char_column_policy &policy);
2083 const char *next_byte () const { return m_next; }
2084 int bytes_processed () const { return m_next - m_begin; }
2085 int bytes_left () const { return m_bytes_left; }
2086 bool done () const { return !bytes_left (); }
2087 int display_cols_processed () const { return m_display_cols; }
2088
2089- int process_next_codepoint ();
2090+ int process_next_codepoint (cpp_decoded_char *out);
2091 int advance_display_cols (int n);
2092
2093 private:
2094 const char *const m_begin;
2095 const char *m_next;
2096 size_t m_bytes_left;
2097- const int m_tabstop;
2098+ const cpp_char_column_policy &m_policy;
2099 int m_display_cols;
2100 };
2101
2102 /* Convenience functions that are simple use cases for class
2103 cpp_display_width_computation. Tab characters will be expanded to spaces
2104- as determined by TABSTOP. */
2105+ as determined by POLICY.m_tabstop, and non-printable-ASCII characters
2106+ will be escaped as per POLICY. */
2107+
2108 int cpp_byte_column_to_display_column (const char *data, int data_length,
2109- int column, int tabstop);
2110+ int column,
2111+ const cpp_char_column_policy &policy);
2112 inline int cpp_display_width (const char *data, int data_length,
2113- int tabstop)
2114+ const cpp_char_column_policy &policy)
2115 {
2116 return cpp_byte_column_to_display_column (data, data_length, data_length,
2117- tabstop);
2118+ policy);
2119 }
2120 int cpp_display_column_to_byte_column (const char *data, int data_length,
2121- int display_col, int tabstop);
2122+ int display_col,
2123+ const cpp_char_column_policy &policy);
2124 int cpp_wcwidth (cppchar_t c);
2125
2126 #endif /* ! LIBCPP_CPPLIB_H */
2127diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
2128--- a/libcpp/include/line-map.h 2020-07-22 23:35:18.712399623 -0700
2129+++ b/libcpp/include/line-map.h 2021-12-25 01:30:50.685688757 -0800
2130@@ -1732,6 +1732,18 @@ class rich_location
2131 const diagnostic_path *get_path () const { return m_path; }
2132 void set_path (const diagnostic_path *path) { m_path = path; }
2133
2134+ /* A flag for hinting that the diagnostic involves character encoding
2135+ issues, and thus that it will be helpful to the user if we show some
2136+ representation of how the characters in the pertinent source lines
2137+ are encoded.
2138+ The default is false (i.e. do not escape).
2139+ When set to true, non-ASCII bytes in the pertinent source lines will
2140+ be escaped in a manner controlled by the user-supplied option
2141+ -fdiagnostics-escape-format=, so that the user can better understand
2142+ what's going on with the encoding in their source file. */
2143+ bool escape_on_output_p () const { return m_escape_on_output; }
2144+ void set_escape_on_output (bool flag) { m_escape_on_output = flag; }
2145+
2146 private:
2147 bool reject_impossible_fixit (location_t where);
2148 void stop_supporting_fixits ();
2149@@ -1758,6 +1770,7 @@ protected:
2150 bool m_fixits_cannot_be_auto_applied;
2151
2152 const diagnostic_path *m_path;
2153+ bool m_escape_on_output;
2154 };
2155
2156 /* A struct for the result of range_label::get_text: a NUL-terminated buffer
2157diff --git a/libcpp/internal.h b/libcpp/internal.h
2158--- a/libcpp/internal.h 2020-07-22 23:35:18.712399623 -0700
2159+++ b/libcpp/internal.h 2021-12-25 01:30:50.685688757 -0800
2160@@ -758,6 +758,9 @@ struct _cpp_dir_only_callbacks
2161 extern void _cpp_preprocess_dir_only (cpp_reader *,
2162 const struct _cpp_dir_only_callbacks *);
2163
2164+/* In errors.c */
2165+extern location_t cpp_diagnostic_get_current_location (cpp_reader *);
2166+
2167 /* In traditional.c. */
2168 extern bool _cpp_scan_out_logical_line (cpp_reader *, cpp_macro *, bool);
2169 extern bool _cpp_read_logical_line_trad (cpp_reader *);
2170@@ -946,6 +949,26 @@ int linemap_get_expansion_line (class li
2171 const char* linemap_get_expansion_filename (class line_maps *,
2172 location_t);
2173
2174+/* A subclass of rich_location for emitting a diagnostic
2175+ at the current location of the reader, but flagging
2176+ it with set_escape_on_output (true). */
2177+class encoding_rich_location : public rich_location
2178+{
2179+ public:
2180+ encoding_rich_location (cpp_reader *pfile)
2181+ : rich_location (pfile->line_table,
2182+ cpp_diagnostic_get_current_location (pfile))
2183+ {
2184+ set_escape_on_output (true);
2185+ }
2186+
2187+ encoding_rich_location (cpp_reader *pfile, location_t loc)
2188+ : rich_location (pfile->line_table, loc)
2189+ {
2190+ set_escape_on_output (true);
2191+ }
2192+};
2193+
2194 #ifdef __cplusplus
2195 }
2196 #endif
2197diff --git a/libcpp/lex.c b/libcpp/lex.c
2198--- a/libcpp/lex.c 2021-12-24 20:23:45.568762024 -0800
2199+++ b/libcpp/lex.c 2021-12-25 01:30:50.685688757 -0800
2200@@ -1268,7 +1268,11 @@ skip_whitespace (cpp_reader *pfile, cppc
2201 while (is_nvspace (c));
2202
2203 if (saw_NUL)
2204- cpp_error (pfile, CPP_DL_WARNING, "null character(s) ignored");
2205+ {
2206+ encoding_rich_location rich_loc (pfile);
2207+ cpp_error_at (pfile, CPP_DL_WARNING, &rich_loc,
2208+ "null character(s) ignored");
2209+ }
2210
2211 buffer->cur--;
2212 }
2213@@ -1297,6 +1301,28 @@ warn_about_normalization (cpp_reader *pf
2214 if (CPP_OPTION (pfile, warn_normalize) < NORMALIZE_STATE_RESULT (s)
2215 && !pfile->state.skipping)
2216 {
2217+ location_t loc = token->src_loc;
2218+
2219+ /* If possible, create a location range for the token. */
2220+ if (loc >= RESERVED_LOCATION_COUNT
2221+ && token->type != CPP_EOF
2222+ /* There must be no line notes to process. */
2223+ && (!(pfile->buffer->cur
2224+ >= pfile->buffer->notes[pfile->buffer->cur_note].pos
2225+ && !pfile->overlaid_buffer)))
2226+ {
2227+ source_range tok_range;
2228+ tok_range.m_start = loc;
2229+ tok_range.m_finish
2230+ = linemap_position_for_column (pfile->line_table,
2231+ CPP_BUF_COLUMN (pfile->buffer,
2232+ pfile->buffer->cur));
2233+ loc = COMBINE_LOCATION_DATA (pfile->line_table,
2234+ loc, tok_range, NULL);
2235+ }
2236+
2237+ encoding_rich_location rich_loc (pfile, loc);
2238+
2239 /* Make sure that the token is printed using UCNs, even
2240 if we'd otherwise happily print UTF-8. */
2241 unsigned char *buf = XNEWVEC (unsigned char, cpp_token_len (token));
2242@@ -1304,11 +1330,11 @@ warn_about_normalization (cpp_reader *pf
2243
2244 sz = cpp_spell_token (pfile, token, buf, false) - buf;
2245 if (NORMALIZE_STATE_RESULT (s) == normalized_C)
2246- cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
2247- "`%.*s' is not in NFKC", (int) sz, buf);
2248+ cpp_warning_at (pfile, CPP_W_NORMALIZE, &rich_loc,
2249+ "`%.*s' is not in NFKC", (int) sz, buf);
2250 else
2251- cpp_warning_with_line (pfile, CPP_W_NORMALIZE, token->src_loc, 0,
2252- "`%.*s' is not in NFC", (int) sz, buf);
2253+ cpp_warning_at (pfile, CPP_W_NORMALIZE, &rich_loc,
2254+ "`%.*s' is not in NFC", (int) sz, buf);
2255 free (buf);
2256 }
2257 }
2258diff --git a/libcpp/line-map.c b/libcpp/line-map.c
2259--- a/libcpp/line-map.c 2020-07-22 23:35:18.712399623 -0700
2260+++ b/libcpp/line-map.c 2021-12-25 01:30:50.685688757 -0800
2261@@ -2007,7 +2007,8 @@ rich_location::rich_location (line_maps
2262 m_fixit_hints (),
2263 m_seen_impossible_fixit (false),
2264 m_fixits_cannot_be_auto_applied (false),
2265- m_path (NULL)
2266+ m_path (NULL),
2267+ m_escape_on_output (false)
2268 {
2269 add_range (loc, SHOW_RANGE_WITH_CARET, label);
2270 }
diff --git a/meta/recipes-devtools/gcc/gcc/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch b/meta/recipes-devtools/gcc/gcc/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch
deleted file mode 100644
index 823cc8b668..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0002-aarch64-Introduce-SLS-mitigation-for-RET-and-BR-inst.patch
+++ /dev/null
@@ -1,607 +0,0 @@
1Upstream-Status: Backport
2Signed-off-by: Ross Burton <ross.burton@arm.com>
3
4From b1204d16e1ec96a4aa89e44de8990e2499ffdb22 Mon Sep 17 00:00:00 2001
5From: Matthew Malcomson <matthew.malcomson@arm.com>
6Date: Thu, 9 Jul 2020 09:11:59 +0100
7Subject: [PATCH 2/3] aarch64: Introduce SLS mitigation for RET and BR
8 instructions
9
10Instructions following RET or BR are not necessarily executed. In order
11to avoid speculation past RET and BR we can simply append a speculation
12barrier.
13
14Since these speculation barriers will not be architecturally executed,
15they are not expected to add a high performance penalty.
16
17The speculation barrier is to be SB when targeting architectures which
18have this enabled, and DSB SY + ISB otherwise.
19
20We add tests for each of the cases where such an instruction was seen.
21
22This is implemented by modifying each machine description pattern that
23emits either a RET or a BR instruction. We choose not to use something
24like `TARGET_ASM_FUNCTION_EPILOGUE` since it does not affect the
25`indirect_jump`, `jump`, `sibcall_insn` and `sibcall_value_insn`
26patterns and we find it preferable to implement the functionality in the
27same way for every pattern.
28
29There is one particular case which is slightly tricky. The
30implementation of TARGET_ASM_TRAMPOLINE_TEMPLATE uses a BR which needs
31to be mitigated against. The trampoline template is used *once* per
32compilation unit, and the TRAMPOLINE_SIZE is exposed to the user via the
33builtin macro __LIBGCC_TRAMPOLINE_SIZE__.
34In the future we may implement function specific attributes to turn on
35and off hardening on a per-function basis.
36The fixed nature of the trampoline described above implies it will be
37safer to ensure this speculation barrier is always used.
38
39Testing:
40 Bootstrap and regtest done on aarch64-none-linux
41 Used a temporary hack(1) to use these options on every test in the
42 testsuite and a script to check that the output never emitted an
43 unmitigated RET or BR.
44
451) Temporary hack was a change to the testsuite to always use
46`-save-temps` and run a script on the assembly output of those
47compilations which produced one to ensure every RET or BR is immediately
48followed by a speculation barrier.
49
50gcc/ChangeLog:
51
52 * config/aarch64/aarch64-protos.h (aarch64_sls_barrier): New.
53 * config/aarch64/aarch64.c (aarch64_output_casesi): Emit
54 speculation barrier after BR instruction if needs be.
55 (aarch64_trampoline_init): Handle ptr_mode value & adjust size
56 of code copied.
57 (aarch64_sls_barrier): New.
58 (aarch64_asm_trampoline_template): Add needed barriers.
59 * config/aarch64/aarch64.h (AARCH64_ISA_SB): New.
60 (TARGET_SB): New.
61 (TRAMPOLINE_SIZE): Account for barrier.
62 * config/aarch64/aarch64.md (indirect_jump, *casesi_dispatch,
63 simple_return, *do_return, *sibcall_insn, *sibcall_value_insn):
64 Emit barrier if needs be, also account for possible barrier using
65 "sls_length" attribute.
66 (sls_length): New attribute.
67 (length): Determine default using any non-default sls_length
68 value.
69
70gcc/testsuite/ChangeLog:
71
72 * gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c: New test.
73 * gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c:
74 New test.
75 * gcc.target/aarch64/sls-mitigation/sls-mitigation.exp: New file.
76 * lib/target-supports.exp (check_effective_target_aarch64_asm_sb_ok):
77 New proc.
78---
79 gcc/config/aarch64/aarch64-protos.h | 1 +
80 gcc/config/aarch64/aarch64.c | 41 ++++++-
81 gcc/config/aarch64/aarch64.h | 10 +-
82 gcc/config/aarch64/aarch64.md | 76 +++++++++----
83 .../aarch64/sls-mitigation/sls-miti-retbr-pacret.c | 21 ++++
84 .../aarch64/sls-mitigation/sls-miti-retbr.c | 119 +++++++++++++++++++++
85 .../aarch64/sls-mitigation/sls-mitigation.exp | 73 +++++++++++++
86 gcc/testsuite/lib/target-supports.exp | 2 +-
87 8 files changed, 318 insertions(+), 25 deletions(-)
88 create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c
89 create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c
90 create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp
91
92diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
93index eb5f4b4..ee0ffde 100644
94--- a/gcc/config/aarch64/aarch64-protos.h
95+++ b/gcc/config/aarch64/aarch64-protos.h
96@@ -781,6 +781,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
97
98 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
99
100+const char *aarch64_sls_barrier (int);
101 extern bool aarch64_harden_sls_retbr_p (void);
102 extern bool aarch64_harden_sls_blr_p (void);
103
104diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
105index 437a9cf..44e3d1f 100644
106--- a/gcc/config/aarch64/aarch64.c
107+++ b/gcc/config/aarch64/aarch64.c
108@@ -10852,8 +10852,8 @@ aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
109 static void
110 aarch64_asm_trampoline_template (FILE *f)
111 {
112- int offset1 = 16;
113- int offset2 = 20;
114+ int offset1 = 24;
115+ int offset2 = 28;
116
117 if (aarch64_bti_enabled ())
118 {
119@@ -10876,6 +10876,17 @@ aarch64_asm_trampoline_template (FILE *f)
120 }
121 asm_fprintf (f, "\tbr\t%s\n", reg_names [IP1_REGNUM]);
122
123+ /* We always emit a speculation barrier.
124+ This is because the same trampoline template is used for every nested
125+ function. Since nested functions are not particularly common or
126+ performant we don't worry too much about the extra instructions to copy
127+ around.
128+ This is not yet a problem, since we have not yet implemented function
129+ specific attributes to choose between hardening against straight line
130+ speculation or not, but such function specific attributes are likely to
131+ happen in the future. */
132+ asm_fprintf (f, "\tdsb\tsy\n\tisb\n");
133+
134 /* The trampoline needs an extra padding instruction. In case if BTI is
135 enabled the padding instruction is replaced by the BTI instruction at
136 the beginning. */
137@@ -10890,10 +10901,14 @@ static void
138 aarch64_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
139 {
140 rtx fnaddr, mem, a_tramp;
141- const int tramp_code_sz = 16;
142+ const int tramp_code_sz = 24;
143
144 /* Don't need to copy the trailing D-words, we fill those in below. */
145- emit_block_move (m_tramp, assemble_trampoline_template (),
146+ /* We create our own memory address in Pmode so that `emit_block_move` can
147+ use parts of the backend which expect Pmode addresses. */
148+ rtx temp = convert_memory_address (Pmode, XEXP (m_tramp, 0));
149+ emit_block_move (gen_rtx_MEM (BLKmode, temp),
150+ assemble_trampoline_template (),
151 GEN_INT (tramp_code_sz), BLOCK_OP_NORMAL);
152 mem = adjust_address (m_tramp, ptr_mode, tramp_code_sz);
153 fnaddr = XEXP (DECL_RTL (fndecl), 0);
154@@ -11084,6 +11099,8 @@ aarch64_output_casesi (rtx *operands)
155 output_asm_insn (buf, operands);
156 output_asm_insn (patterns[index][1], operands);
157 output_asm_insn ("br\t%3", operands);
158+ output_asm_insn (aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()),
159+ operands);
160 assemble_label (asm_out_file, label);
161 return "";
162 }
163@@ -22924,6 +22941,22 @@ aarch64_file_end_indicate_exec_stack ()
164 #undef GNU_PROPERTY_AARCH64_FEATURE_1_BTI
165 #undef GNU_PROPERTY_AARCH64_FEATURE_1_AND
166
167+/* Helper function for straight line speculation.
168+ Return what barrier should be emitted for straight line speculation
169+ mitigation.
170+ When not mitigating against straight line speculation this function returns
171+ an empty string.
172+ When mitigating against straight line speculation, use:
173+ * SB when the v8.5-A SB extension is enabled.
174+ * DSB+ISB otherwise. */
175+const char *
176+aarch64_sls_barrier (int mitigation_required)
177+{
178+ return mitigation_required
179+ ? (TARGET_SB ? "sb" : "dsb\tsy\n\tisb")
180+ : "";
181+}
182+
183 /* Target-specific selftests. */
184
185 #if CHECKING_P
186diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
187index 1ce23c6..c21015f 100644
188--- a/gcc/config/aarch64/aarch64.h
189+++ b/gcc/config/aarch64/aarch64.h
190@@ -281,6 +281,7 @@ extern unsigned aarch64_architecture_version;
191 #define AARCH64_ISA_F32MM (aarch64_isa_flags & AARCH64_FL_F32MM)
192 #define AARCH64_ISA_F64MM (aarch64_isa_flags & AARCH64_FL_F64MM)
193 #define AARCH64_ISA_BF16 (aarch64_isa_flags & AARCH64_FL_BF16)
194+#define AARCH64_ISA_SB (aarch64_isa_flags & AARCH64_FL_SB)
195
196 /* Crypto is an optional extension to AdvSIMD. */
197 #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO)
198@@ -378,6 +379,9 @@ extern unsigned aarch64_architecture_version;
199 #define TARGET_FIX_ERR_A53_835769_DEFAULT 1
200 #endif
201
202+/* SB instruction is enabled through +sb. */
203+#define TARGET_SB (AARCH64_ISA_SB)
204+
205 /* Apply the workaround for Cortex-A53 erratum 835769. */
206 #define TARGET_FIX_ERR_A53_835769 \
207 ((aarch64_fix_a53_err835769 == 2) \
208@@ -1058,8 +1062,10 @@ typedef struct
209
210 #define RETURN_ADDR_RTX aarch64_return_addr
211
212-/* BTI c + 3 insns + 2 pointer-sized entries. */
213-#define TRAMPOLINE_SIZE (TARGET_ILP32 ? 24 : 32)
214+/* BTI c + 3 insns
215+ + sls barrier of DSB + ISB.
216+ + 2 pointer-sized entries. */
217+#define TRAMPOLINE_SIZE (24 + (TARGET_ILP32 ? 8 : 16))
218
219 /* Trampolines contain dwords, so must be dword aligned. */
220 #define TRAMPOLINE_ALIGNMENT 64
221diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
222index 8c8be3c..dda04ee 100644
223--- a/gcc/config/aarch64/aarch64.md
224+++ b/gcc/config/aarch64/aarch64.md
225@@ -407,10 +407,25 @@
226 ;; Attribute that specifies whether the alternative uses MOVPRFX.
227 (define_attr "movprfx" "no,yes" (const_string "no"))
228
229+;; Attribute to specify that an alternative has the length of a single
230+;; instruction plus a speculation barrier.
231+(define_attr "sls_length" "none,retbr,casesi" (const_string "none"))
232+
233 (define_attr "length" ""
234 (cond [(eq_attr "movprfx" "yes")
235 (const_int 8)
236- ] (const_int 4)))
237+
238+ (eq_attr "sls_length" "retbr")
239+ (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 4)
240+ (match_test "TARGET_SB") (const_int 8)]
241+ (const_int 12))
242+
243+ (eq_attr "sls_length" "casesi")
244+ (cond [(match_test "!aarch64_harden_sls_retbr_p ()") (const_int 16)
245+ (match_test "TARGET_SB") (const_int 20)]
246+ (const_int 24))
247+ ]
248+ (const_int 4)))
249
250 ;; Strictly for compatibility with AArch32 in pipeline models, since AArch64 has
251 ;; no predicated insns.
252@@ -447,8 +462,12 @@
253 (define_insn "indirect_jump"
254 [(set (pc) (match_operand:DI 0 "register_operand" "r"))]
255 ""
256- "br\\t%0"
257- [(set_attr "type" "branch")]
258+ {
259+ output_asm_insn ("br\\t%0", operands);
260+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
261+ }
262+ [(set_attr "type" "branch")
263+ (set_attr "sls_length" "retbr")]
264 )
265
266 (define_insn "jump"
267@@ -765,7 +784,7 @@
268 "*
269 return aarch64_output_casesi (operands);
270 "
271- [(set_attr "length" "16")
272+ [(set_attr "sls_length" "casesi")
273 (set_attr "type" "branch")]
274 )
275
276@@ -844,18 +863,23 @@
277 [(return)]
278 ""
279 {
280+ const char *ret = NULL;
281 if (aarch64_return_address_signing_enabled ()
282 && TARGET_ARMV8_3
283 && !crtl->calls_eh_return)
284 {
285 if (aarch64_ra_sign_key == AARCH64_KEY_B)
286- return "retab";
287+ ret = "retab";
288 else
289- return "retaa";
290+ ret = "retaa";
291 }
292- return "ret";
293+ else
294+ ret = "ret";
295+ output_asm_insn (ret, operands);
296+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
297 }
298- [(set_attr "type" "branch")]
299+ [(set_attr "type" "branch")
300+ (set_attr "sls_length" "retbr")]
301 )
302
303 (define_expand "return"
304@@ -867,8 +891,12 @@
305 (define_insn "simple_return"
306 [(simple_return)]
307 ""
308- "ret"
309- [(set_attr "type" "branch")]
310+ {
311+ output_asm_insn ("ret", operands);
312+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
313+ }
314+ [(set_attr "type" "branch")
315+ (set_attr "sls_length" "retbr")]
316 )
317
318 (define_insn "*cb<optab><mode>1"
319@@ -1066,10 +1094,16 @@
320 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
321 (return)]
322 "SIBLING_CALL_P (insn)"
323- "@
324- br\\t%0
325- b\\t%c0"
326- [(set_attr "type" "branch, branch")]
327+ {
328+ if (which_alternative == 0)
329+ {
330+ output_asm_insn ("br\\t%0", operands);
331+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
332+ }
333+ return "b\\t%c0";
334+ }
335+ [(set_attr "type" "branch, branch")
336+ (set_attr "sls_length" "retbr,none")]
337 )
338
339 (define_insn "*sibcall_value_insn"
340@@ -1080,10 +1114,16 @@
341 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
342 (return)]
343 "SIBLING_CALL_P (insn)"
344- "@
345- br\\t%1
346- b\\t%c1"
347- [(set_attr "type" "branch, branch")]
348+ {
349+ if (which_alternative == 0)
350+ {
351+ output_asm_insn ("br\\t%1", operands);
352+ return aarch64_sls_barrier (aarch64_harden_sls_retbr_p ());
353+ }
354+ return "b\\t%c1";
355+ }
356+ [(set_attr "type" "branch, branch")
357+ (set_attr "sls_length" "retbr,none")]
358 )
359
360 ;; Call subroutine returning any type.
361diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c
362new file mode 100644
363index 0000000..fa1887a
364--- /dev/null
365+++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr-pacret.c
366@@ -0,0 +1,21 @@
367+/* Avoid ILP32 since pacret is only available for LP64 */
368+/* { dg-do compile { target { ! ilp32 } } } */
369+/* { dg-additional-options "-mharden-sls=retbr -mbranch-protection=pac-ret -march=armv8.3-a" } */
370+
371+/* Testing the do_return pattern for retaa and retab. */
372+long retbr_subcall(void);
373+long retbr_do_return_retaa(void)
374+{
375+ return retbr_subcall()+1;
376+}
377+
378+__attribute__((target("branch-protection=pac-ret+b-key")))
379+long retbr_do_return_retab(void)
380+{
381+ return retbr_subcall()+1;
382+}
383+
384+/* Ensure there are no BR or RET instructions which are not directly followed
385+ by a speculation barrier. */
386+/* { dg-final { scan-assembler-not {\t(br|ret|retaa|retab)\tx[0-9][0-9]?\n\t(?!dsb\tsy\n\tisb)} } } */
387+/* { dg-final { scan-assembler-not {ret\t} } } */
388diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c
389new file mode 100644
390index 0000000..76b8d03
391--- /dev/null
392+++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-retbr.c
393@@ -0,0 +1,119 @@
394+/* We ensure that -Wpedantic is off since it complains about the trampolines
395+ we explicitly want to test. */
396+/* { dg-additional-options "-mharden-sls=retbr -Wno-pedantic " } */
397+/*
398+ Ensure that the SLS hardening of RET and BR leaves no unprotected RET/BR
399+ instructions.
400+ */
401+typedef int (foo) (int, int);
402+typedef void (bar) (int, int);
403+struct sls_testclass {
404+ foo *x;
405+ bar *y;
406+ int left;
407+ int right;
408+};
409+
410+int
411+retbr_sibcall_value_insn (struct sls_testclass x)
412+{
413+ return x.x(x.left, x.right);
414+}
415+
416+void
417+retbr_sibcall_insn (struct sls_testclass x)
418+{
419+ x.y(x.left, x.right);
420+}
421+
422+/* Aim to test two different returns.
423+ One that introduces a tail call in the middle of the function, and one that
424+ has a normal return. */
425+int
426+retbr_multiple_returns (struct sls_testclass x)
427+{
428+ int temp;
429+ if (x.left % 10)
430+ return x.x(x.left, 100);
431+ else if (x.right % 20)
432+ {
433+ return x.x(x.left * x.right, 100);
434+ }
435+ temp = x.left % x.right;
436+ temp *= 100;
437+ temp /= 2;
438+ return temp % 3;
439+}
440+
441+void
442+retbr_multiple_returns_void (struct sls_testclass x)
443+{
444+ if (x.left % 10)
445+ {
446+ x.y(x.left, 100);
447+ }
448+ else if (x.right % 20)
449+ {
450+ x.y(x.left * x.right, 100);
451+ }
452+ return;
453+}
454+
455+/* Testing the casesi jump via register. */
456+__attribute__ ((optimize ("Os")))
457+int
458+retbr_casesi_dispatch (struct sls_testclass x)
459+{
460+ switch (x.left)
461+ {
462+ case -5:
463+ return -2;
464+ case -3:
465+ return -1;
466+ case 0:
467+ return 0;
468+ case 3:
469+ return 1;
470+ case 5:
471+ break;
472+ default:
473+ __builtin_unreachable ();
474+ }
475+ return x.right;
476+}
477+
478+/* Testing the BR in trampolines is mitigated against. */
479+void f1 (void *);
480+void f3 (void *, void (*)(void *));
481+void f2 (void *);
482+
483+int
484+retbr_trampolines (void *a, int b)
485+{
486+ if (!b)
487+ {
488+ f1 (a);
489+ return 1;
490+ }
491+ if (b)
492+ {
493+ void retbr_tramp_internal (void *c)
494+ {
495+ if (c == a)
496+ f2 (c);
497+ }
498+ f3 (a, retbr_tramp_internal);
499+ }
500+ return 0;
501+}
502+
503+/* Testing the indirect_jump pattern. */
504+void
505+retbr_indirect_jump (int *buf)
506+{
507+ __builtin_longjmp(buf, 1);
508+}
509+
510+/* Ensure there are no BR or RET instructions which are not directly followed
511+ by a speculation barrier. */
512+/* { dg-final { scan-assembler-not {\t(br|ret|retaa|retab)\tx[0-9][0-9]?\n\t(?!dsb\tsy\n\tisb|sb)} } } */
513diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp
514new file mode 100644
515index 0000000..8122503
516--- /dev/null
517+++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-mitigation.exp
518@@ -0,0 +1,73 @@
519+# Regression driver for SLS mitigation on AArch64.
520+# Copyright (C) 2020 Free Software Foundation, Inc.
521+# Contributed by ARM Ltd.
522+#
523+# This file is part of GCC.
524+#
525+# GCC is free software; you can redistribute it and/or modify it
526+# under the terms of the GNU General Public License as published by
527+# the Free Software Foundation; either version 3, or (at your option)
528+# any later version.
529+#
530+# GCC is distributed in the hope that it will be useful, but
531+# WITHOUT ANY WARRANTY; without even the implied warranty of
532+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
533+# General Public License for more details.
534+#
535+# You should have received a copy of the GNU General Public License
536+# along with GCC; see the file COPYING3. If not see
537+# <http://www.gnu.org/licenses/>. */
538+
539+# Exit immediately if this isn't an AArch64 target.
540+if {![istarget aarch64*-*-*] } then {
541+ return
542+}
543+
544+# Load support procs.
545+load_lib gcc-dg.exp
546+load_lib torture-options.exp
547+
548+# If a testcase doesn't have special options, use these.
549+global DEFAULT_CFLAGS
550+if ![info exists DEFAULT_CFLAGS] then {
551+ set DEFAULT_CFLAGS " "
552+}
553+
554+# Initialize `dg'.
555+dg-init
556+torture-init
557+
558+# Use different architectures as well as the normal optimisation options.
559+# (i.e. use both SB and DSB+ISB barriers).
560+
561+set save-dg-do-what-default ${dg-do-what-default}
562+# Main loop.
563+# Run with torture tests (i.e. a bunch of different optimisation levels) just
564+# to increase test coverage.
565+set dg-do-what-default assemble
566+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
567+ "-save-temps" $DEFAULT_CFLAGS
568+
569+# Run the same tests but this time with SB extension.
570+# Since not all supported assemblers will support that extension we decide
571+# whether to assemble or just compile based on whether the extension is
572+# supported for the available assembler.
573+
574+set templist {}
575+foreach x $DG_TORTURE_OPTIONS {
576+ lappend templist "$x -march=armv8.3-a+sb "
577+ lappend templist "$x -march=armv8-a+sb "
578+}
579+set-torture-options $templist
580+if { [check_effective_target_aarch64_asm_sb_ok] } {
581+ set dg-do-what-default assemble
582+} else {
583+ set dg-do-what-default compile
584+}
585+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cCS\]]] \
586+ "-save-temps" $DEFAULT_CFLAGS
587+set dg-do-what-default ${save-dg-do-what-default}
588+
589+# All done.
590+torture-finish
591+dg-finish
592diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
593index 8a186dd..9d2e093 100644
594--- a/gcc/testsuite/lib/target-supports.exp
595+++ b/gcc/testsuite/lib/target-supports.exp
596@@ -9432,7 +9432,7 @@ proc check_effective_target_aarch64_tiny { } {
597 # various architecture extensions via the .arch_extension pseudo-op.
598
599 foreach { aarch64_ext } { "fp" "simd" "crypto" "crc" "lse" "dotprod" "sve"
600- "i8mm" "f32mm" "f64mm" "bf16" } {
601+ "i8mm" "f32mm" "f64mm" "bf16" "sb" } {
602 eval [string map [list FUNC $aarch64_ext] {
603 proc check_effective_target_aarch64_asm_FUNC_ok { } {
604 if { [istarget aarch64*-*-*] } {
605--
6062.7.4
607
diff --git a/meta/recipes-devtools/gcc/gcc/0003-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0003-CVE-2021-42574.patch
new file mode 100644
index 0000000000..6bfaf8402d
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0003-CVE-2021-42574.patch
@@ -0,0 +1,1724 @@
1From 51c500269bf53749b107807d84271385fad35628 Mon Sep 17 00:00:00 2001
2From: Marek Polacek <polacek@redhat.com>
3Date: Wed, 6 Oct 2021 14:33:59 -0400
4Subject: [PATCH] libcpp: Implement -Wbidi-chars for CVE-2021-42574 [PR103026]
5
6From a link below:
7"An issue was discovered in the Bidirectional Algorithm in the Unicode
8Specification through 14.0. It permits the visual reordering of
9characters via control sequences, which can be used to craft source code
10that renders different logic than the logical ordering of tokens
11ingested by compilers and interpreters. Adversaries can leverage this to
12encode source code for compilers accepting Unicode such that targeted
13vulnerabilities are introduced invisibly to human reviewers."
14
15More info:
16https://nvd.nist.gov/vuln/detail/CVE-2021-42574
17https://trojansource.codes/
18
19This is not a compiler bug. However, to mitigate the problem, this patch
20implements -Wbidi-chars=[none|unpaired|any] to warn about possibly
21misleading Unicode bidirectional control characters the preprocessor may
22encounter.
23
24The default is =unpaired, which warns about improperly terminated
25bidirectional control characters; e.g. a LRE without its corresponding PDF.
26The level =any warns about any use of bidirectional control characters.
27
28This patch handles both UCNs and UTF-8 characters. UCNs designating
29bidi characters in identifiers are accepted since r204886. Then r217144
30enabled -fextended-identifiers by default. Extended characters in C/C++
31identifiers have been accepted since r275979. However, this patch still
32warns about mixing UTF-8 and UCN bidi characters; there seems to be no
33good reason to allow mixing them.
34
35We warn in different contexts: comments (both C and C++-style), string
36literals, character constants, and identifiers. Expectedly, UCNs are ignored
37in comments and raw string literals. The bidirectional control characters
38can nest so this patch handles that as well.
39
40I have not included nor tested this at all with Fortran (which also has
41string literals and line comments).
42
43Dave M. posted patches improving diagnostic involving Unicode characters.
44This patch does not make use of this new infrastructure yet.
45
46 PR preprocessor/103026
47
48gcc/c-family/ChangeLog:
49
50 * c.opt (Wbidi-chars, Wbidi-chars=): New option.
51
52gcc/ChangeLog:
53
54 * doc/invoke.texi: Document -Wbidi-chars.
55
56libcpp/ChangeLog:
57
58 * include/cpplib.h (enum cpp_bidirectional_level): New.
59 (struct cpp_options): Add cpp_warn_bidirectional.
60 (enum cpp_warning_reason): Add CPP_W_BIDIRECTIONAL.
61 * internal.h (struct cpp_reader): Add warn_bidi_p member
62 function.
63 * init.c (cpp_create_reader): Set cpp_warn_bidirectional.
64 * lex.c (bidi): New namespace.
65 (get_bidi_utf8): New function.
66 (get_bidi_ucn): Likewise.
67 (maybe_warn_bidi_on_close): Likewise.
68 (maybe_warn_bidi_on_char): Likewise.
69 (_cpp_skip_block_comment): Implement warning about bidirectional
70 control characters.
71 (skip_line_comment): Likewise.
72 (forms_identifier_p): Likewise.
73 (lex_identifier): Likewise.
74 (lex_string): Likewise.
75 (lex_raw_string): Likewise.
76
77gcc/testsuite/ChangeLog:
78
79 * c-c++-common/Wbidi-chars-1.c: New test.
80 * c-c++-common/Wbidi-chars-2.c: New test.
81 * c-c++-common/Wbidi-chars-3.c: New test.
82 * c-c++-common/Wbidi-chars-4.c: New test.
83 * c-c++-common/Wbidi-chars-5.c: New test.
84 * c-c++-common/Wbidi-chars-6.c: New test.
85 * c-c++-common/Wbidi-chars-7.c: New test.
86 * c-c++-common/Wbidi-chars-8.c: New test.
87 * c-c++-common/Wbidi-chars-9.c: New test.
88 * c-c++-common/Wbidi-chars-10.c: New test.
89 * c-c++-common/Wbidi-chars-11.c: New test.
90 * c-c++-common/Wbidi-chars-12.c: New test.
91 * c-c++-common/Wbidi-chars-13.c: New test.
92 * c-c++-common/Wbidi-chars-14.c: New test.
93 * c-c++-common/Wbidi-chars-15.c: New test.
94 * c-c++-common/Wbidi-chars-16.c: New test.
95 * c-c++-common/Wbidi-chars-17.c: New test.
96
97CVE: CVE-2021-42574
98Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=51c500269bf53749b107807d84271385fad35628]
99Signed-off-by: Pgowda <pgowda.cve@gmail.com>
100
101---
102 gcc/c-family/c.opt | 24 ++
103 gcc/doc/invoke.texi | 21 +-
104 gcc/testsuite/c-c++-common/Wbidi-chars-1.c | 12 +
105 gcc/testsuite/c-c++-common/Wbidi-chars-10.c | 27 ++
106 gcc/testsuite/c-c++-common/Wbidi-chars-11.c | 13 +
107 gcc/testsuite/c-c++-common/Wbidi-chars-12.c | 19 +
108 gcc/testsuite/c-c++-common/Wbidi-chars-13.c | 17 +
109 gcc/testsuite/c-c++-common/Wbidi-chars-14.c | 38 ++
110 gcc/testsuite/c-c++-common/Wbidi-chars-15.c | 59 +++
111 gcc/testsuite/c-c++-common/Wbidi-chars-16.c | 26 ++
112 gcc/testsuite/c-c++-common/Wbidi-chars-17.c | 30 ++
113 gcc/testsuite/c-c++-common/Wbidi-chars-2.c | 9 +
114 gcc/testsuite/c-c++-common/Wbidi-chars-3.c | 11 +
115 gcc/testsuite/c-c++-common/Wbidi-chars-4.c | 188 +++++++++
116 gcc/testsuite/c-c++-common/Wbidi-chars-5.c | 188 +++++++++
117 gcc/testsuite/c-c++-common/Wbidi-chars-6.c | 155 ++++++++
118 gcc/testsuite/c-c++-common/Wbidi-chars-7.c | 9 +
119 gcc/testsuite/c-c++-common/Wbidi-chars-8.c | 13 +
120 gcc/testsuite/c-c++-common/Wbidi-chars-9.c | 29 ++
121 libcpp/include/cpplib.h | 18 +-
122 libcpp/init.c | 1 +
123 libcpp/internal.h | 7 +
124 libcpp/lex.c | 408 +++++++++++++++++++-
125 23 files changed, 1315 insertions(+), 7 deletions(-)
126 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-1.c
127 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-10.c
128 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-11.c
129 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-12.c
130 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-13.c
131 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-14.c
132 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-15.c
133 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-16.c
134 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-17.c
135 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-2.c
136 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-3.c
137 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-4.c
138 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-5.c
139 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-6.c
140 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-7.c
141 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-8.c
142 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-9.c
143
144diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
145--- a/gcc/c-family/c.opt 2021-12-25 01:29:12.915317374 -0800
146+++ b/gcc/c-family/c.opt 2021-12-25 01:36:22.040018701 -0800
147@@ -350,6 +350,30 @@ Wbad-function-cast
148 C ObjC Var(warn_bad_function_cast) Warning
149 Warn about casting functions to incompatible types.
150
151+Wbidi-chars
152+C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none)
153+;
154+
155+Wbidi-chars=
156+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level)
157+-Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters.
158+
159+; Required for these enum values.
160+SourceInclude
161+cpplib.h
162+
163+Enum
164+Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized)
165+
166+EnumValue
167+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none)
168+
169+EnumValue
170+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired)
171+
172+EnumValue
173+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any)
174+
175 Wbool-compare
176 C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
177 Warn about boolean expression compared with an integer value different from true/false.
178diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
179--- a/gcc/doc/invoke.texi 2021-12-25 01:35:33.284883488 -0800
180+++ b/gcc/doc/invoke.texi 2021-12-25 01:36:22.048018559 -0800
181@@ -310,7 +310,9 @@ Objective-C and Objective-C++ Dialects}.
182 -Warith-conversion @gol
183 -Warray-bounds -Warray-bounds=@var{n} @gol
184 -Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
185--Wno-attribute-warning -Wbool-compare -Wbool-operation @gol
186+-Wno-attribute-warning @gol
187+-Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol
188+-Wbool-compare -Wbool-operation @gol
189 -Wno-builtin-declaration-mismatch @gol
190 -Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol
191 -Wc11-c2x-compat @gol
192@@ -6860,6 +6862,23 @@ Attributes considered include @code{allo
193 This is the default. You can disable these warnings with either
194 @option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}.
195
196+@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]}
197+@opindex Wbidi-chars=
198+@opindex Wbidi-chars
199+@opindex Wno-bidi-chars
200+Warn about possibly misleading UTF-8 bidirectional control characters in
201+comments, string literals, character constants, and identifiers. Such
202+characters can change left-to-right writing direction into right-to-left
203+(and vice versa), which can cause confusion between the logical order and
204+visual order. This may be dangerous; for instance, it may seem that a piece
205+of code is not commented out, whereas it in fact is.
206+
207+There are three levels of warning supported by GCC@. The default is
208+@option{-Wbidi-chars=unpaired}, which warns about improperly terminated
209+bidi contexts. @option{-Wbidi-chars=none} turns the warning off.
210+@option{-Wbidi-chars=any} warns about any use of bidirectional control
211+characters.
212+
213 @item -Wbool-compare
214 @opindex Wno-bool-compare
215 @opindex Wbool-compare
216diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c
217--- a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c 1969-12-31 16:00:00.000000000 -0800
218+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c 2021-12-25 01:36:22.048018559 -0800
219@@ -0,0 +1,27 @@
220+/* PR preprocessor/103026 */
221+/* { dg-do compile } */
222+/* { dg-options "-Wbidi-chars=unpaired" } */
223+/* More nesting testing. */
224+
225+/* RLE‫ LRI⁦ PDF‬ PDI⁩*/
226+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
227+int LRE_\u202a_PDF_\u202c;
228+int LRE_\u202a_PDF_\u202c_LRE_\u202a_PDF_\u202c;
229+int LRE_\u202a_LRI_\u2066_PDF_\u202c_PDI_\u2069;
230+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
231+int RLE_\u202b_RLI_\u2067_PDF_\u202c_PDI_\u2069;
232+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
233+int RLE_\u202b_RLI_\u2067_PDI_\u2069_PDF_\u202c;
234+int FSI_\u2068_LRO_\u202d_PDI_\u2069_PDF_\u202c;
235+int FSI_\u2068;
236+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
237+int FSI_\u2068_PDI_\u2069;
238+int FSI_\u2068_FSI_\u2068_PDI_\u2069;
239+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
240+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
241+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
242+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
243+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDF_\u202c;
244+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
245+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_FSI_\u2068_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
246+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
247diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c
248--- a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c 1969-12-31 16:00:00.000000000 -0800
249+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c 2021-12-25 01:36:22.048018559 -0800
250@@ -0,0 +1,13 @@
251+/* PR preprocessor/103026 */
252+/* { dg-do compile } */
253+/* { dg-options "-Wbidi-chars=unpaired" } */
254+/* Test that we warn when mixing UCN and UTF-8. */
255+
256+int LRE_‪_PDF_\u202c;
257+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
258+int LRE_\u202a_PDF_‬_;
259+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
260+const char *s1 = "LRE_‪_PDF_\u202c";
261+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
262+const char *s2 = "LRE_\u202a_PDF_‬";
263+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
264diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-12.c b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c
265--- a/gcc/testsuite/c-c++-common/Wbidi-chars-12.c 1969-12-31 16:00:00.000000000 -0800
266+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c 2021-12-25 01:36:22.048018559 -0800
267@@ -0,0 +1,19 @@
268+/* PR preprocessor/103026 */
269+/* { dg-do compile { target { c || c++11 } } } */
270+/* { dg-options "-Wbidi-chars=any" } */
271+/* Test raw strings. */
272+
273+const char *s1 = R"(a b c LRE‪ 1 2 3 PDF‬ x y z)";
274+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
275+const char *s2 = R"(a b c RLE‫ 1 2 3 PDF‬ x y z)";
276+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
277+const char *s3 = R"(a b c LRO‭ 1 2 3 PDF‬ x y z)";
278+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
279+const char *s4 = R"(a b c RLO‮ 1 2 3 PDF‬ x y z)";
280+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
281+const char *s7 = R"(a b c FSI⁨ 1 2 3 PDI⁩ x y) z";
282+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
283+const char *s8 = R"(a b c PDI⁩ x y )z";
284+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
285+const char *s9 = R"(a b c PDF‬ x y z)";
286+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
287diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-13.c b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c
288--- a/gcc/testsuite/c-c++-common/Wbidi-chars-13.c 1969-12-31 16:00:00.000000000 -0800
289+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c 2021-12-25 01:36:22.048018559 -0800
290@@ -0,0 +1,17 @@
291+/* PR preprocessor/103026 */
292+/* { dg-do compile { target { c || c++11 } } } */
293+/* { dg-options "-Wbidi-chars=unpaired" } */
294+/* Test raw strings. */
295+
296+const char *s1 = R"(a b c LRE‪ 1 2 3)";
297+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
298+const char *s2 = R"(a b c RLE‫ 1 2 3)";
299+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
300+const char *s3 = R"(a b c LRO‭ 1 2 3)";
301+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
302+const char *s4 = R"(a b c FSI⁨ 1 2 3)";
303+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
304+const char *s5 = R"(a b c LRI⁦ 1 2 3)";
305+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
306+const char *s6 = R"(a b c RLI⁧ 1 2 3)";
307+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
308diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c
309--- a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c 1969-12-31 16:00:00.000000000 -0800
310+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c 2021-12-25 01:36:22.048018559 -0800
311@@ -0,0 +1,38 @@
312+/* PR preprocessor/103026 */
313+/* { dg-do compile } */
314+/* { dg-options "-Wbidi-chars=unpaired" } */
315+/* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs,
316+ or RLOs. */
317+
318+/* LRI_⁦_LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩*/
319+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
320+// LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩
321+// LRI_⁦_RLO_‮_RLE_‫_RLE_‫_PDI_⁩
322+// LRI_⁦_RLO_‮_RLE_‫_PDI_⁩
323+// FSI_⁨_RLO_‮_PDI_⁩
324+// FSI_⁨_FSI_⁨_RLO_‮_PDI_⁩
325+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
326+
327+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069;
328+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
329+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069;
330+int LRI_\u2066_LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069;
331+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
332+int PDI_\u2069;
333+int LRI_\u2066_PDI_\u2069;
334+int RLI_\u2067_PDI_\u2069;
335+int LRE_\u202a_LRI_\u2066_PDI_\u2069;
336+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
337+int LRI_\u2066_LRE_\u202a_PDF_\u202c_PDI_\u2069;
338+int LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
339+int RLI_\u2067_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
340+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
341+int FSI_\u2068_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
342+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
343+int RLO_\u202e_PDI_\u2069;
344+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
345+int RLI_\u2067_PDI_\u2069_RLI_\u2067;
346+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
347+int FSI_\u2068_PDF_\u202c_PDI_\u2069;
348+int FSI_\u2068_FSI_\u2068_PDF_\u202c_PDI_\u2069;
349+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
350diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-15.c b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c
351--- a/gcc/testsuite/c-c++-common/Wbidi-chars-15.c 1969-12-31 16:00:00.000000000 -0800
352+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c 2021-12-25 01:36:22.048018559 -0800
353@@ -0,0 +1,59 @@
354+/* PR preprocessor/103026 */
355+/* { dg-do compile } */
356+/* { dg-options "-Wbidi-chars=unpaired" } */
357+/* Test unpaired bidi control chars in multiline comments. */
358+
359+/*
360+ * LRE‪ end
361+ */
362+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
363+/*
364+ * RLE‫ end
365+ */
366+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
367+/*
368+ * LRO‭ end
369+ */
370+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
371+/*
372+ * RLO‮ end
373+ */
374+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
375+/*
376+ * LRI⁦ end
377+ */
378+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
379+/*
380+ * RLI⁧ end
381+ */
382+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
383+/*
384+ * FSI⁨ end
385+ */
386+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
387+/* LRE‪
388+ PDF‬ */
389+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
390+/* FSI⁨
391+ PDI⁩ */
392+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
393+
394+/* LRE<‪>
395+ *
396+ */
397+/* { dg-warning "unpaired" "" { target *-*-* } .-3 } */
398+
399+/*
400+ * LRE<‪>
401+ */
402+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
403+
404+/*
405+ *
406+ * LRE<‪> */
407+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
408+
409+/* RLI<⁧> */ /* PDI<⁩> */
410+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
411+/* LRE<‪> */ /* PDF<‬> */
412+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
413diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c
414--- a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c 1969-12-31 16:00:00.000000000 -0800
415+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c 2021-12-25 01:36:22.048018559 -0800
416@@ -0,0 +1,26 @@
417+/* PR preprocessor/103026 */
418+/* { dg-do compile } */
419+/* { dg-options "-Wbidi-chars=any" } */
420+/* Test LTR/RTL chars. */
421+
422+/* LTR<‎> */
423+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
424+// LTR<‎>
425+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
426+/* RTL<‏> */
427+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
428+// RTL<‏>
429+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
430+
431+const char *s1 = "LTR<‎>";
432+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
433+const char *s2 = "LTR\u200e";
434+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
435+const char *s3 = "LTR\u200E";
436+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
437+const char *s4 = "RTL<‏>";
438+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
439+const char *s5 = "RTL\u200f";
440+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
441+const char *s6 = "RTL\u200F";
442+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
443diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c
444--- a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c 1969-12-31 16:00:00.000000000 -0800
445+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c 2021-12-25 01:36:22.048018559 -0800
446@@ -0,0 +1,30 @@
447+/* PR preprocessor/103026 */
448+/* { dg-do compile } */
449+/* { dg-options "-Wbidi-chars=unpaired" } */
450+/* Test LTR/RTL chars. */
451+
452+/* LTR<‎> */
453+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
454+// LTR<‎>
455+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
456+/* RTL<‏> */
457+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
458+// RTL<‏>
459+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
460+int ltr_\u200e;
461+/* { dg-error "universal character " "" { target *-*-* } .-1 } */
462+int rtl_\u200f;
463+/* { dg-error "universal character " "" { target *-*-* } .-1 } */
464+
465+const char *s1 = "LTR<‎>";
466+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
467+const char *s2 = "LTR\u200e";
468+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
469+const char *s3 = "LTR\u200E";
470+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
471+const char *s4 = "RTL<‏>";
472+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
473+const char *s5 = "RTL\u200f";
474+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
475+const char *s6 = "RTL\u200F";
476+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
477diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-1.c b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c
478--- a/gcc/testsuite/c-c++-common/Wbidi-chars-1.c 1969-12-31 16:00:00.000000000 -0800
479+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c 2021-12-25 01:36:22.048018559 -0800
480@@ -0,0 +1,12 @@
481+/* PR preprocessor/103026 */
482+/* { dg-do compile } */
483+
484+int main() {
485+ int isAdmin = 0;
486+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */
487+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
488+ __builtin_printf("You are an admin.\n");
489+ /* end admins only ‮ { ⁦*/
490+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
491+ return 0;
492+}
493diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-2.c b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c
494--- a/gcc/testsuite/c-c++-common/Wbidi-chars-2.c 1969-12-31 16:00:00.000000000 -0800
495+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c 2021-12-25 01:36:22.048018559 -0800
496@@ -0,0 +1,9 @@
497+/* PR preprocessor/103026 */
498+/* { dg-do compile } */
499+
500+int main() {
501+ /* Say hello; newline⁧/*/ return 0 ;
502+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
503+ __builtin_printf("Hello world.\n");
504+ return 0;
505+}
506diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-3.c b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c
507--- a/gcc/testsuite/c-c++-common/Wbidi-chars-3.c 1969-12-31 16:00:00.000000000 -0800
508+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c 2021-12-25 01:36:22.048018559 -0800
509@@ -0,0 +1,11 @@
510+/* PR preprocessor/103026 */
511+/* { dg-do compile } */
512+
513+int main() {
514+ const char* access_level = "user";
515+ if (__builtin_strcmp(access_level, "user‮ ⁦// Check if admin⁩ ⁦")) {
516+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
517+ __builtin_printf("You are an admin.\n");
518+ }
519+ return 0;
520+}
521diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c
522--- a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c 1969-12-31 16:00:00.000000000 -0800
523+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c 2021-12-25 01:36:22.048018559 -0800
524@@ -0,0 +1,188 @@
525+/* PR preprocessor/103026 */
526+/* { dg-do compile } */
527+/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */
528+/* Test all bidi chars in various contexts (identifiers, comments,
529+ string literals, character constants), both UCN and UTF-8. The bidi
530+ chars here are properly terminated, except for the character constants. */
531+
532+/* a b c LRE‪ 1 2 3 PDF‬ x y z */
533+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
534+/* a b c RLE‫ 1 2 3 PDF‬ x y z */
535+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
536+/* a b c LRO‭ 1 2 3 PDF‬ x y z */
537+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
538+/* a b c RLO‮ 1 2 3 PDF‬ x y z */
539+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
540+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */
541+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
542+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */
543+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
544+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */
545+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
546+
547+/* Same but C++ comments instead. */
548+// a b c LRE‪ 1 2 3 PDF‬ x y z
549+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
550+// a b c RLE‫ 1 2 3 PDF‬ x y z
551+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
552+// a b c LRO‭ 1 2 3 PDF‬ x y z
553+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
554+// a b c RLO‮ 1 2 3 PDF‬ x y z
555+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
556+// a b c LRI⁦ 1 2 3 PDI⁩ x y z
557+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
558+// a b c RLI⁧ 1 2 3 PDI⁩ x y
559+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
560+// a b c FSI⁨ 1 2 3 PDI⁩ x y z
561+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
562+
563+/* Here we're closing an unopened context, warn when =any. */
564+/* a b c PDI⁩ x y z */
565+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
566+/* a b c PDF‬ x y z */
567+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
568+// a b c PDI⁩ x y z
569+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
570+// a b c PDF‬ x y z
571+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
572+
573+/* Multiline comments. */
574+/* a b c PDI⁩ x y z
575+ */
576+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */
577+/* a b c PDF‬ x y z
578+ */
579+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */
580+/* first
581+ a b c PDI⁩ x y z
582+ */
583+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */
584+/* first
585+ a b c PDF‬ x y z
586+ */
587+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */
588+/* first
589+ a b c PDI⁩ x y z */
590+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
591+/* first
592+ a b c PDF‬ x y z */
593+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
594+
595+void
596+g1 ()
597+{
598+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z";
599+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
600+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z";
601+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
602+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z";
603+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
604+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z";
605+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
606+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z";
607+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
608+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z";
609+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
610+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z";
611+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
612+ const char *s8 = "a b c PDI⁩ x y z";
613+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
614+ const char *s9 = "a b c PDF‬ x y z";
615+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
616+
617+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z";
618+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
619+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z";
620+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
621+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z";
622+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
623+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z";
624+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
625+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z";
626+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
627+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z";
628+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
629+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z";
630+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
631+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z";
632+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
633+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z";
634+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
635+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z";
636+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
637+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z";
638+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
639+}
640+
641+void
642+g2 ()
643+{
644+ const char c1 = '\u202a';
645+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
646+ const char c2 = '\u202A';
647+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
648+ const char c3 = '\u202b';
649+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
650+ const char c4 = '\u202B';
651+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
652+ const char c5 = '\u202d';
653+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
654+ const char c6 = '\u202D';
655+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
656+ const char c7 = '\u202e';
657+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
658+ const char c8 = '\u202E';
659+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
660+ const char c9 = '\u2066';
661+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
662+ const char c10 = '\u2067';
663+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
664+ const char c11 = '\u2068';
665+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
666+}
667+
668+int a‪b‬c;
669+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
670+int a‫b‬c;
671+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
672+int a‭b‬c;
673+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
674+int a‮b‬c;
675+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
676+int a⁦b⁩c;
677+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
678+int a⁧b⁩c;
679+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
680+int a⁨b⁩c;
681+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
682+int A‬X;
683+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
684+int A\u202cY;
685+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
686+int A\u202CY2;
687+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
688+
689+int d\u202ae\u202cf;
690+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
691+int d\u202Ae\u202cf2;
692+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
693+int d\u202be\u202cf;
694+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
695+int d\u202Be\u202cf2;
696+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
697+int d\u202de\u202cf;
698+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
699+int d\u202De\u202cf2;
700+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
701+int d\u202ee\u202cf;
702+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
703+int d\u202Ee\u202cf2;
704+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
705+int d\u2066e\u2069f;
706+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
707+int d\u2067e\u2069f;
708+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
709+int d\u2068e\u2069f;
710+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
711+int X\u2069;
712+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
713diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c
714--- a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c 1969-12-31 16:00:00.000000000 -0800
715+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c 2021-12-25 01:36:22.048018559 -0800
716@@ -0,0 +1,188 @@
717+/* PR preprocessor/103026 */
718+/* { dg-do compile } */
719+/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */
720+/* Test all bidi chars in various contexts (identifiers, comments,
721+ string literals, character constants), both UCN and UTF-8. The bidi
722+ chars here are properly terminated, except for the character constants. */
723+
724+/* a b c LRE‪ 1 2 3 PDF‬ x y z */
725+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
726+/* a b c RLE‫ 1 2 3 PDF‬ x y z */
727+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
728+/* a b c LRO‭ 1 2 3 PDF‬ x y z */
729+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
730+/* a b c RLO‮ 1 2 3 PDF‬ x y z */
731+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
732+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */
733+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
734+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */
735+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
736+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */
737+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
738+
739+/* Same but C++ comments instead. */
740+// a b c LRE‪ 1 2 3 PDF‬ x y z
741+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
742+// a b c RLE‫ 1 2 3 PDF‬ x y z
743+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
744+// a b c LRO‭ 1 2 3 PDF‬ x y z
745+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
746+// a b c RLO‮ 1 2 3 PDF‬ x y z
747+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
748+// a b c LRI⁦ 1 2 3 PDI⁩ x y z
749+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
750+// a b c RLI⁧ 1 2 3 PDI⁩ x y
751+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
752+// a b c FSI⁨ 1 2 3 PDI⁩ x y z
753+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
754+
755+/* Here we're closing an unopened context, warn when =any. */
756+/* a b c PDI⁩ x y z */
757+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
758+/* a b c PDF‬ x y z */
759+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
760+// a b c PDI⁩ x y z
761+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
762+// a b c PDF‬ x y z
763+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
764+
765+/* Multiline comments. */
766+/* a b c PDI⁩ x y z
767+ */
768+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
769+/* a b c PDF‬ x y z
770+ */
771+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
772+/* first
773+ a b c PDI⁩ x y z
774+ */
775+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
776+/* first
777+ a b c PDF‬ x y z
778+ */
779+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
780+/* first
781+ a b c PDI⁩ x y z */
782+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
783+/* first
784+ a b c PDF‬ x y z */
785+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
786+
787+void
788+g1 ()
789+{
790+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z";
791+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
792+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z";
793+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
794+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z";
795+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
796+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z";
797+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
798+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z";
799+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
800+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z";
801+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
802+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z";
803+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
804+ const char *s8 = "a b c PDI⁩ x y z";
805+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
806+ const char *s9 = "a b c PDF‬ x y z";
807+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
808+
809+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z";
810+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
811+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z";
812+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
813+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z";
814+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
815+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z";
816+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
817+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z";
818+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
819+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z";
820+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
821+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z";
822+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
823+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z";
824+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
825+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z";
826+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
827+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z";
828+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
829+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z";
830+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
831+}
832+
833+void
834+g2 ()
835+{
836+ const char c1 = '\u202a';
837+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
838+ const char c2 = '\u202A';
839+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
840+ const char c3 = '\u202b';
841+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
842+ const char c4 = '\u202B';
843+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
844+ const char c5 = '\u202d';
845+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
846+ const char c6 = '\u202D';
847+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
848+ const char c7 = '\u202e';
849+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
850+ const char c8 = '\u202E';
851+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
852+ const char c9 = '\u2066';
853+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
854+ const char c10 = '\u2067';
855+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
856+ const char c11 = '\u2068';
857+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
858+}
859+
860+int a‪b‬c;
861+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
862+int a‫b‬c;
863+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
864+int a‭b‬c;
865+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
866+int a‮b‬c;
867+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
868+int a⁦b⁩c;
869+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
870+int a⁧b⁩c;
871+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
872+int a⁨b⁩c;
873+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
874+int A‬X;
875+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
876+int A\u202cY;
877+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
878+int A\u202CY2;
879+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
880+
881+int d\u202ae\u202cf;
882+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
883+int d\u202Ae\u202cf2;
884+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
885+int d\u202be\u202cf;
886+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
887+int d\u202Be\u202cf2;
888+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
889+int d\u202de\u202cf;
890+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
891+int d\u202De\u202cf2;
892+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
893+int d\u202ee\u202cf;
894+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
895+int d\u202Ee\u202cf2;
896+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
897+int d\u2066e\u2069f;
898+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
899+int d\u2067e\u2069f;
900+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
901+int d\u2068e\u2069f;
902+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
903+int X\u2069;
904+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
905diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c
906--- a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c 1969-12-31 16:00:00.000000000 -0800
907+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c 2021-12-25 01:36:22.052018489 -0800
908@@ -0,0 +1,155 @@
909+/* PR preprocessor/103026 */
910+/* { dg-do compile } */
911+/* { dg-options "-Wbidi-chars=unpaired" } */
912+/* Test nesting of bidi chars in various contexts. */
913+
914+/* Terminated by the wrong char: */
915+/* a b c LRE‪ 1 2 3 PDI⁩ x y z */
916+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
917+/* a b c RLE‫ 1 2 3 PDI⁩ x y z*/
918+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
919+/* a b c LRO‭ 1 2 3 PDI⁩ x y z */
920+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
921+/* a b c RLO‮ 1 2 3 PDI⁩ x y z */
922+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
923+/* a b c LRI⁦ 1 2 3 PDF‬ x y z */
924+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
925+/* a b c RLI⁧ 1 2 3 PDF‬ x y z */
926+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
927+/* a b c FSI⁨ 1 2 3 PDF‬ x y z*/
928+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
929+
930+/* LRE‪ PDF‬ */
931+/* LRE‪ LRE‪ PDF‬ PDF‬ */
932+/* PDF‬ LRE‪ PDF‬ */
933+/* LRE‪ PDF‬ LRE‪ PDF‬ */
934+/* LRE‪ LRE‪ PDF‬ */
935+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
936+/* PDF‬ LRE‪ */
937+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
938+
939+// a b c LRE‪ 1 2 3 PDI⁩ x y z
940+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
941+// a b c RLE‫ 1 2 3 PDI⁩ x y z*/
942+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
943+// a b c LRO‭ 1 2 3 PDI⁩ x y z
944+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
945+// a b c RLO‮ 1 2 3 PDI⁩ x y z
946+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
947+// a b c LRI⁦ 1 2 3 PDF‬ x y z
948+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
949+// a b c RLI⁧ 1 2 3 PDF‬ x y z
950+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
951+// a b c FSI⁨ 1 2 3 PDF‬ x y z
952+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
953+
954+// LRE‪ PDF‬
955+// LRE‪ LRE‪ PDF‬ PDF‬
956+// PDF‬ LRE‪ PDF‬
957+// LRE‪ PDF‬ LRE‪ PDF‬
958+// LRE‪ LRE‪ PDF‬
959+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
960+// PDF‬ LRE‪
961+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
962+
963+void
964+g1 ()
965+{
966+ const char *s1 = "a b c LRE‪ 1 2 3 PDI⁩ x y z";
967+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
968+ const char *s2 = "a b c LRE\u202a 1 2 3 PDI\u2069 x y z";
969+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
970+ const char *s3 = "a b c RLE‫ 1 2 3 PDI⁩ x y ";
971+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
972+ const char *s4 = "a b c RLE\u202b 1 2 3 PDI\u2069 x y z";
973+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
974+ const char *s5 = "a b c LRO‭ 1 2 3 PDI⁩ x y z";
975+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
976+ const char *s6 = "a b c LRO\u202d 1 2 3 PDI\u2069 x y z";
977+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
978+ const char *s7 = "a b c RLO‮ 1 2 3 PDI⁩ x y z";
979+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
980+ const char *s8 = "a b c RLO\u202e 1 2 3 PDI\u2069 x y z";
981+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
982+ const char *s9 = "a b c LRI⁦ 1 2 3 PDF‬ x y z";
983+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
984+ const char *s10 = "a b c LRI\u2066 1 2 3 PDF\u202c x y z";
985+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
986+ const char *s11 = "a b c RLI⁧ 1 2 3 PDF‬ x y z\
987+ ";
988+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
989+ const char *s12 = "a b c RLI\u2067 1 2 3 PDF\u202c x y z";
990+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
991+ const char *s13 = "a b c FSI⁨ 1 2 3 PDF‬ x y z";
992+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
993+ const char *s14 = "a b c FSI\u2068 1 2 3 PDF\u202c x y z";
994+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
995+ const char *s15 = "PDF‬ LRE‪";
996+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
997+ const char *s16 = "PDF\u202c LRE\u202a";
998+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
999+ const char *s17 = "LRE‪ PDF‬";
1000+ const char *s18 = "LRE\u202a PDF\u202c";
1001+ const char *s19 = "LRE‪ LRE‪ PDF‬ PDF‬";
1002+ const char *s20 = "LRE\u202a LRE\u202a PDF\u202c PDF\u202c";
1003+ const char *s21 = "PDF‬ LRE‪ PDF‬";
1004+ const char *s22 = "PDF\u202c LRE\u202a PDF\u202c";
1005+ const char *s23 = "LRE‪ LRE‪ PDF‬";
1006+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1007+ const char *s24 = "LRE\u202a LRE\u202a PDF\u202c";
1008+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1009+ const char *s25 = "PDF‬ LRE‪";
1010+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1011+ const char *s26 = "PDF\u202c LRE\u202a";
1012+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1013+ const char *s27 = "PDF‬ LRE\u202a";
1014+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1015+ const char *s28 = "PDF\u202c LRE‪";
1016+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1017+}
1018+
1019+int aLRE‪bPDI⁩;
1020+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1021+int A\u202aB\u2069C;
1022+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1023+int aRLE‫bPDI⁩;
1024+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1025+int a\u202bB\u2069c;
1026+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1027+int aLRO‭bPDI⁩;
1028+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1029+int a\u202db\u2069c2;
1030+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1031+int aRLO‮bPDI⁩;
1032+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1033+int a\u202eb\u2069;
1034+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1035+int aLRI⁦bPDF‬;
1036+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1037+int a\u2066b\u202c;
1038+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1039+int aRLI⁧bPDF‬c
1040+;
1041+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
1042+int a\u2067b\u202c;
1043+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1044+int aFSI⁨bPDF‬;
1045+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1046+int a\u2068b\u202c;
1047+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1048+int aFSI⁨bPD\u202C;
1049+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1050+int aFSI\u2068bPDF‬_;
1051+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1052+int aLRE‪bPDF‬b;
1053+int A\u202aB\u202c;
1054+int a_LRE‪_LRE‪_b_PDF‬_PDF‬;
1055+int A\u202aA\u202aB\u202cB\u202c;
1056+int aPDF‬bLREadPDF‬;
1057+int a_\u202C_\u202a_\u202c;
1058+int a_LRE‪_b_PDF‬_c_LRE‪_PDF‬;
1059+int a_\u202a_\u202c_\u202a_\u202c_;
1060+int a_LRE‪_b_PDF‬_c_LRE‪;
1061+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1062+int a_\u202a_\u202c_\u202a_;
1063+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1064diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c
1065--- a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c 1969-12-31 16:00:00.000000000 -0800
1066+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c 2021-12-25 01:36:22.052018489 -0800
1067@@ -0,0 +1,9 @@
1068+/* PR preprocessor/103026 */
1069+/* { dg-do compile } */
1070+/* { dg-options "-Wbidi-chars=any" } */
1071+/* Test we ignore UCNs in comments. */
1072+
1073+// a b c \u202a 1 2 3
1074+// a b c \u202A 1 2 3
1075+/* a b c \u202a 1 2 3 */
1076+/* a b c \u202A 1 2 3 */
1077diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c
1078--- a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c 1969-12-31 16:00:00.000000000 -0800
1079+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c 2021-12-25 01:36:22.052018489 -0800
1080@@ -0,0 +1,13 @@
1081+/* PR preprocessor/103026 */
1082+/* { dg-do compile } */
1083+/* { dg-options "-Wbidi-chars=any" } */
1084+/* Test \u vs \U. */
1085+
1086+int a_\u202A;
1087+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
1088+int a_\u202a_2;
1089+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
1090+int a_\U0000202A_3;
1091+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
1092+int a_\U0000202a_4;
1093+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
1094diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c
1095--- a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c 1969-12-31 16:00:00.000000000 -0800
1096+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c 2021-12-25 01:36:22.052018489 -0800
1097@@ -0,0 +1,29 @@
1098+/* PR preprocessor/103026 */
1099+/* { dg-do compile } */
1100+/* { dg-options "-Wbidi-chars=unpaired" } */
1101+/* Test that we properly separate bidi contexts (comment/identifier/character
1102+ constant/string literal). */
1103+
1104+/* LRE ->‪<- */ int pdf_\u202c_1;
1105+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1106+/* RLE ->‫<- */ int pdf_\u202c_2;
1107+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1108+/* LRO ->‭<- */ int pdf_\u202c_3;
1109+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1110+/* RLO ->‮<- */ int pdf_\u202c_4;
1111+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1112+/* LRI ->⁦<-*/ int pdi_\u2069_1;
1113+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1114+/* RLI ->⁧<- */ int pdi_\u2069_12;
1115+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1116+/* FSI ->⁨<- */ int pdi_\u2069_3;
1117+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1118+
1119+const char *s1 = "LRE\u202a"; /* PDF ->‬<- */
1120+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1121+/* LRE ->‪<- */ const char *s2 = "PDF\u202c";
1122+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1123+const char *s3 = "LRE\u202a"; int pdf_\u202c_5;
1124+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1125+int lre_\u202a; const char *s4 = "PDF\u202c";
1126+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
1127diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
1128--- a/libcpp/include/cpplib.h 2021-12-25 01:35:33.288883417 -0800
1129+++ b/libcpp/include/cpplib.h 2021-12-25 01:36:22.052018489 -0800
1130@@ -308,6 +308,17 @@ enum cpp_normalize_level {
1131 normalized_none
1132 };
1133
1134+/* The possible bidirectional control characters checking levels, from least
1135+ restrictive to most. */
1136+enum cpp_bidirectional_level {
1137+ /* No checking. */
1138+ bidirectional_none,
1139+ /* Only detect unpaired uses of bidirectional control characters. */
1140+ bidirectional_unpaired,
1141+ /* Detect any use of bidirectional control characters. */
1142+ bidirectional_any
1143+};
1144+
1145 /* This structure is nested inside struct cpp_reader, and
1146 carries all the options visible to the command line. */
1147 struct cpp_options
1148@@ -515,6 +526,10 @@ struct cpp_options
1149 /* True if warn about differences between C++98 and C++11. */
1150 bool cpp_warn_cxx11_compat;
1151
1152+ /* Nonzero if bidirectional control characters checking is on. See enum
1153+ cpp_bidirectional_level. */
1154+ unsigned char cpp_warn_bidirectional;
1155+
1156 /* Dependency generation. */
1157 struct
1158 {
1159@@ -613,7 +628,8 @@ enum cpp_warning_reason {
1160 CPP_W_C90_C99_COMPAT,
1161 CPP_W_C11_C2X_COMPAT,
1162 CPP_W_CXX11_COMPAT,
1163- CPP_W_EXPANSION_TO_DEFINED
1164+ CPP_W_EXPANSION_TO_DEFINED,
1165+ CPP_W_BIDIRECTIONAL
1166 };
1167
1168 /* Callback for header lookup for HEADER, which is the name of a
1169diff --git a/libcpp/init.c b/libcpp/init.c
1170--- a/libcpp/init.c 2021-12-25 01:29:12.931317107 -0800
1171+++ b/libcpp/init.c 2021-12-25 01:36:22.052018489 -0800
1172@@ -215,6 +215,7 @@ cpp_create_reader (enum c_lang lang, cpp
1173 = ENABLE_CANONICAL_SYSTEM_HEADERS;
1174 CPP_OPTION (pfile, ext_numeric_literals) = 1;
1175 CPP_OPTION (pfile, warn_date_time) = 0;
1176+ CPP_OPTION (pfile, cpp_warn_bidirectional) = bidirectional_unpaired;
1177
1178 /* Default CPP arithmetic to something sensible for the host for the
1179 benefit of dumb users like fix-header. */
1180diff --git a/libcpp/internal.h b/libcpp/internal.h
1181--- a/libcpp/internal.h 2021-12-25 01:35:33.288883417 -0800
1182+++ b/libcpp/internal.h 2021-12-25 01:36:22.052018489 -0800
1183@@ -581,6 +581,10 @@ struct cpp_reader
1184 /* If non-zero, the lexer will use this location for the next token
1185 instead of getting a location from the linemap. */
1186 location_t forced_token_location;
1187+ bool warn_bidi_p () const
1188+ {
1189+ return CPP_OPTION (this, cpp_warn_bidirectional) != bidirectional_none;
1190+ }
1191 };
1192
1193 /* Character classes. Based on the more primitive macros in safe-ctype.h.
1194diff --git a/libcpp/lex.c b/libcpp/lex.c
1195--- a/libcpp/lex.c 2021-12-25 01:35:33.288883417 -0800
1196+++ b/libcpp/lex.c 2021-12-25 01:36:22.052018489 -0800
1197@@ -1164,6 +1164,324 @@ _cpp_process_line_notes (cpp_reader *pfi
1198 }
1199 }
1200
1201+namespace bidi {
1202+ enum class kind {
1203+ NONE, LRE, RLE, LRO, RLO, LRI, RLI, FSI, PDF, PDI, LTR, RTL
1204+ };
1205+
1206+ /* All the UTF-8 encodings of bidi characters start with E2. */
1207+ constexpr uchar utf8_start = 0xe2;
1208+
1209+ /* A vector holding currently open bidi contexts. We use a char for
1210+ each context, its LSB is 1 if it represents a PDF context, 0 if it
1211+ represents a PDI context. The next bit is 1 if this context was open
1212+ by a bidi character written as a UCN, and 0 when it was UTF-8. */
1213+ semi_embedded_vec <unsigned char, 16> vec;
1214+
1215+ /* Close the whole comment/identifier/string literal/character constant
1216+ context. */
1217+ void on_close ()
1218+ {
1219+ vec.truncate (0);
1220+ }
1221+
1222+ /* Pop the last element in the vector. */
1223+ void pop ()
1224+ {
1225+ unsigned int len = vec.count ();
1226+ gcc_checking_assert (len > 0);
1227+ vec.truncate (len - 1);
1228+ }
1229+
1230+ /* Return the context of the Ith element. */
1231+ kind ctx_at (unsigned int i)
1232+ {
1233+ return (vec[i] & 1) ? kind::PDF : kind::PDI;
1234+ }
1235+
1236+ /* Return which context is currently opened. */
1237+ kind current_ctx ()
1238+ {
1239+ unsigned int len = vec.count ();
1240+ if (len == 0)
1241+ return kind::NONE;
1242+ return ctx_at (len - 1);
1243+ }
1244+
1245+ /* Return true if the current context comes from a UCN origin, that is,
1246+ the bidi char which started this bidi context was written as a UCN. */
1247+ bool current_ctx_ucn_p ()
1248+ {
1249+ unsigned int len = vec.count ();
1250+ gcc_checking_assert (len > 0);
1251+ return (vec[len - 1] >> 1) & 1;
1252+ }
1253+
1254+ /* We've read a bidi char, update the current vector as necessary. */
1255+ void on_char (kind k, bool ucn_p)
1256+ {
1257+ switch (k)
1258+ {
1259+ case kind::LRE:
1260+ case kind::RLE:
1261+ case kind::LRO:
1262+ case kind::RLO:
1263+ vec.push (ucn_p ? 3u : 1u);
1264+ break;
1265+ case kind::LRI:
1266+ case kind::RLI:
1267+ case kind::FSI:
1268+ vec.push (ucn_p ? 2u : 0u);
1269+ break;
1270+ /* PDF terminates the scope of the last LRE, RLE, LRO, or RLO
1271+ whose scope has not yet been terminated. */
1272+ case kind::PDF:
1273+ if (current_ctx () == kind::PDF)
1274+ pop ();
1275+ break;
1276+ /* PDI terminates the scope of the last LRI, RLI, or FSI whose
1277+ scope has not yet been terminated, as well as the scopes of
1278+ any subsequent LREs, RLEs, LROs, or RLOs whose scopes have not
1279+ yet been terminated. */
1280+ case kind::PDI:
1281+ for (int i = vec.count () - 1; i >= 0; --i)
1282+ if (ctx_at (i) == kind::PDI)
1283+ {
1284+ vec.truncate (i);
1285+ break;
1286+ }
1287+ break;
1288+ case kind::LTR:
1289+ case kind::RTL:
1290+ /* These aren't popped by a PDF/PDI. */
1291+ break;
1292+ [[likely]] case kind::NONE:
1293+ break;
1294+ default:
1295+ abort ();
1296+ }
1297+ }
1298+
1299+ /* Return a descriptive string for K. */
1300+ const char *to_str (kind k)
1301+ {
1302+ switch (k)
1303+ {
1304+ case kind::LRE:
1305+ return "U+202A (LEFT-TO-RIGHT EMBEDDING)";
1306+ case kind::RLE:
1307+ return "U+202B (RIGHT-TO-LEFT EMBEDDING)";
1308+ case kind::LRO:
1309+ return "U+202D (LEFT-TO-RIGHT OVERRIDE)";
1310+ case kind::RLO:
1311+ return "U+202E (RIGHT-TO-LEFT OVERRIDE)";
1312+ case kind::LRI:
1313+ return "U+2066 (LEFT-TO-RIGHT ISOLATE)";
1314+ case kind::RLI:
1315+ return "U+2067 (RIGHT-TO-LEFT ISOLATE)";
1316+ case kind::FSI:
1317+ return "U+2068 (FIRST STRONG ISOLATE)";
1318+ case kind::PDF:
1319+ return "U+202C (POP DIRECTIONAL FORMATTING)";
1320+ case kind::PDI:
1321+ return "U+2069 (POP DIRECTIONAL ISOLATE)";
1322+ case kind::LTR:
1323+ return "U+200E (LEFT-TO-RIGHT MARK)";
1324+ case kind::RTL:
1325+ return "U+200F (RIGHT-TO-LEFT MARK)";
1326+ default:
1327+ abort ();
1328+ }
1329+ }
1330+}
1331+
1332+/* Parse a sequence of 3 bytes starting with P and return its bidi code. */
1333+
1334+static bidi::kind
1335+get_bidi_utf8 (const unsigned char *const p)
1336+{
1337+ gcc_checking_assert (p[0] == bidi::utf8_start);
1338+
1339+ if (p[1] == 0x80)
1340+ switch (p[2])
1341+ {
1342+ case 0xaa:
1343+ return bidi::kind::LRE;
1344+ case 0xab:
1345+ return bidi::kind::RLE;
1346+ case 0xac:
1347+ return bidi::kind::PDF;
1348+ case 0xad:
1349+ return bidi::kind::LRO;
1350+ case 0xae:
1351+ return bidi::kind::RLO;
1352+ case 0x8e:
1353+ return bidi::kind::LTR;
1354+ case 0x8f:
1355+ return bidi::kind::RTL;
1356+ default:
1357+ break;
1358+ }
1359+ else if (p[1] == 0x81)
1360+ switch (p[2])
1361+ {
1362+ case 0xa6:
1363+ return bidi::kind::LRI;
1364+ case 0xa7:
1365+ return bidi::kind::RLI;
1366+ case 0xa8:
1367+ return bidi::kind::FSI;
1368+ case 0xa9:
1369+ return bidi::kind::PDI;
1370+ default:
1371+ break;
1372+ }
1373+
1374+ return bidi::kind::NONE;
1375+}
1376+
1377+/* Parse a UCN where P points just past \u or \U and return its bidi code. */
1378+
1379+static bidi::kind
1380+get_bidi_ucn (const unsigned char *p, bool is_U)
1381+{
1382+ /* 6.4.3 Universal Character Names
1383+ \u hex-quad
1384+ \U hex-quad hex-quad
1385+ where \unnnn means \U0000nnnn. */
1386+
1387+ if (is_U)
1388+ {
1389+ if (p[0] != '0' || p[1] != '0' || p[2] != '0' || p[3] != '0')
1390+ return bidi::kind::NONE;
1391+ /* Skip 4B so we can treat \u and \U the same below. */
1392+ p += 4;
1393+ }
1394+
1395+ /* All code points we are looking for start with 20xx. */
1396+ if (p[0] != '2' || p[1] != '0')
1397+ return bidi::kind::NONE;
1398+ else if (p[2] == '2')
1399+ switch (p[3])
1400+ {
1401+ case 'a':
1402+ case 'A':
1403+ return bidi::kind::LRE;
1404+ case 'b':
1405+ case 'B':
1406+ return bidi::kind::RLE;
1407+ case 'c':
1408+ case 'C':
1409+ return bidi::kind::PDF;
1410+ case 'd':
1411+ case 'D':
1412+ return bidi::kind::LRO;
1413+ case 'e':
1414+ case 'E':
1415+ return bidi::kind::RLO;
1416+ default:
1417+ break;
1418+ }
1419+ else if (p[2] == '6')
1420+ switch (p[3])
1421+ {
1422+ case '6':
1423+ return bidi::kind::LRI;
1424+ case '7':
1425+ return bidi::kind::RLI;
1426+ case '8':
1427+ return bidi::kind::FSI;
1428+ case '9':
1429+ return bidi::kind::PDI;
1430+ default:
1431+ break;
1432+ }
1433+ else if (p[2] == '0')
1434+ switch (p[3])
1435+ {
1436+ case 'e':
1437+ case 'E':
1438+ return bidi::kind::LTR;
1439+ case 'f':
1440+ case 'F':
1441+ return bidi::kind::RTL;
1442+ default:
1443+ break;
1444+ }
1445+
1446+ return bidi::kind::NONE;
1447+}
1448+
1449+/* We're closing a bidi context, that is, we've encountered a newline,
1450+ are closing a C-style comment, or are at the end of a string literal,
1451+ character constant, or identifier. Warn if this context was not
1452+ properly terminated by a PDI or PDF. P points to the last character
1453+ in this context. */
1454+
1455+static void
1456+maybe_warn_bidi_on_close (cpp_reader *pfile, const uchar *p)
1457+{
1458+ if (CPP_OPTION (pfile, cpp_warn_bidirectional) == bidirectional_unpaired
1459+ && bidi::vec.count () > 0)
1460+ {
1461+ const location_t loc
1462+ = linemap_position_for_column (pfile->line_table,
1463+ CPP_BUF_COLUMN (pfile->buffer, p));
1464+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
1465+ "unpaired UTF-8 bidirectional control character "
1466+ "detected");
1467+ }
1468+ /* We're done with this context. */
1469+ bidi::on_close ();
1470+}
1471+
1472+/* We're at the beginning or in the middle of an identifier/comment/string
1473+ literal/character constant. Warn if we've encountered a bidi character.
1474+ KIND says which bidi character it was; P points to it in the character
1475+ stream. UCN_P is true iff this bidi character was written as a UCN. */
1476+
1477+static void
1478+maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind,
1479+ bool ucn_p)
1480+{
1481+ if (__builtin_expect (kind == bidi::kind::NONE, 1))
1482+ return;
1483+
1484+ const auto warn_bidi = CPP_OPTION (pfile, cpp_warn_bidirectional);
1485+
1486+ if (warn_bidi != bidirectional_none)
1487+ {
1488+ const location_t loc
1489+ = linemap_position_for_column (pfile->line_table,
1490+ CPP_BUF_COLUMN (pfile->buffer, p));
1491+ /* It seems excessive to warn about a PDI/PDF that is closing
1492+ an opened context because we've already warned about the
1493+ opening character. Except warn when we have a UCN x UTF-8
1494+ mismatch. */
1495+ if (kind == bidi::current_ctx ())
1496+ {
1497+ if (warn_bidi == bidirectional_unpaired
1498+ && bidi::current_ctx_ucn_p () != ucn_p)
1499+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
1500+ "UTF-8 vs UCN mismatch when closing "
1501+ "a context by \"%s\"", bidi::to_str (kind));
1502+ }
1503+ else if (warn_bidi == bidirectional_any)
1504+ {
1505+ if (kind == bidi::kind::PDF || kind == bidi::kind::PDI)
1506+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
1507+ "\"%s\" is closing an unopened context",
1508+ bidi::to_str (kind));
1509+ else
1510+ cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
1511+ "found problematic Unicode character \"%s\"",
1512+ bidi::to_str (kind));
1513+ }
1514+ }
1515+ /* We're done with this context. */
1516+ bidi::on_char (kind, ucn_p);
1517+}
1518+
1519 /* Skip a C-style block comment. We find the end of the comment by
1520 seeing if an asterisk is before every '/' we encounter. Returns
1521 nonzero if comment terminated by EOF, zero otherwise.
1522@@ -1175,6 +1493,7 @@ _cpp_skip_block_comment (cpp_reader *pfi
1523 cpp_buffer *buffer = pfile->buffer;
1524 const uchar *cur = buffer->cur;
1525 uchar c;
1526+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1527
1528 cur++;
1529 if (*cur == '/')
1530@@ -1189,7 +1508,11 @@ _cpp_skip_block_comment (cpp_reader *pfi
1531 if (c == '/')
1532 {
1533 if (cur[-2] == '*')
1534- break;
1535+ {
1536+ if (warn_bidi_p)
1537+ maybe_warn_bidi_on_close (pfile, cur);
1538+ break;
1539+ }
1540
1541 /* Warn about potential nested comments, but not if the '/'
1542 comes immediately before the true comment delimiter.
1543@@ -1208,6 +1531,8 @@ _cpp_skip_block_comment (cpp_reader *pfi
1544 {
1545 unsigned int cols;
1546 buffer->cur = cur - 1;
1547+ if (warn_bidi_p)
1548+ maybe_warn_bidi_on_close (pfile, cur);
1549 _cpp_process_line_notes (pfile, true);
1550 if (buffer->next_line >= buffer->rlimit)
1551 return true;
1552@@ -1218,6 +1543,13 @@ _cpp_skip_block_comment (cpp_reader *pfi
1553
1554 cur = buffer->cur;
1555 }
1556+ /* If this is a beginning of a UTF-8 encoding, it might be
1557+ a bidirectional control character. */
1558+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
1559+ {
1560+ bidi::kind kind = get_bidi_utf8 (cur - 1);
1561+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false);
1562+ }
1563 }
1564
1565 buffer->cur = cur;
1566@@ -1233,9 +1565,31 @@ skip_line_comment (cpp_reader *pfile)
1567 {
1568 cpp_buffer *buffer = pfile->buffer;
1569 location_t orig_line = pfile->line_table->highest_line;
1570+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1571
1572- while (*buffer->cur != '\n')
1573- buffer->cur++;
1574+ if (!warn_bidi_p)
1575+ while (*buffer->cur != '\n')
1576+ buffer->cur++;
1577+ else
1578+ {
1579+ while (*buffer->cur != '\n'
1580+ && *buffer->cur != bidi::utf8_start)
1581+ buffer->cur++;
1582+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0))
1583+ {
1584+ while (*buffer->cur != '\n')
1585+ {
1586+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0))
1587+ {
1588+ bidi::kind kind = get_bidi_utf8 (buffer->cur);
1589+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
1590+ /*ucn_p=*/false);
1591+ }
1592+ buffer->cur++;
1593+ }
1594+ maybe_warn_bidi_on_close (pfile, buffer->cur);
1595+ }
1596+ }
1597
1598 _cpp_process_line_notes (pfile, true);
1599 return orig_line != pfile->line_table->highest_line;
1600@@ -1343,11 +1697,13 @@ static const cppchar_t utf8_signifier =
1601
1602 /* Returns TRUE if the sequence starting at buffer->cur is valid in
1603 an identifier. FIRST is TRUE if this starts an identifier. */
1604+
1605 static bool
1606 forms_identifier_p (cpp_reader *pfile, int first,
1607 struct normalize_state *state)
1608 {
1609 cpp_buffer *buffer = pfile->buffer;
1610+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1611
1612 if (*buffer->cur == '$')
1613 {
1614@@ -1370,6 +1726,13 @@ forms_identifier_p (cpp_reader *pfile, i
1615 cppchar_t s;
1616 if (*buffer->cur >= utf8_signifier)
1617 {
1618+ if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)
1619+ && warn_bidi_p)
1620+ {
1621+ bidi::kind kind = get_bidi_utf8 (buffer->cur);
1622+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
1623+ /*ucn_p=*/false);
1624+ }
1625 if (_cpp_valid_utf8 (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
1626 state, &s))
1627 return true;
1628@@ -1378,6 +1741,13 @@ forms_identifier_p (cpp_reader *pfile, i
1629 && (buffer->cur[1] == 'u' || buffer->cur[1] == 'U'))
1630 {
1631 buffer->cur += 2;
1632+ if (warn_bidi_p)
1633+ {
1634+ bidi::kind kind = get_bidi_ucn (buffer->cur,
1635+ buffer->cur[-1] == 'U');
1636+ maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
1637+ /*ucn_p=*/true);
1638+ }
1639 if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
1640 state, &s, NULL, NULL))
1641 return true;
1642@@ -1486,6 +1856,7 @@ lex_identifier (cpp_reader *pfile, const
1643 const uchar *cur;
1644 unsigned int len;
1645 unsigned int hash = HT_HASHSTEP (0, *base);
1646+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1647
1648 cur = pfile->buffer->cur;
1649 if (! starts_ucn)
1650@@ -1509,6 +1880,8 @@ lex_identifier (cpp_reader *pfile, const
1651 pfile->buffer->cur++;
1652 }
1653 } while (forms_identifier_p (pfile, false, nst));
1654+ if (warn_bidi_p)
1655+ maybe_warn_bidi_on_close (pfile, pfile->buffer->cur);
1656 result = _cpp_interpret_identifier (pfile, base,
1657 pfile->buffer->cur - base);
1658 *spelling = cpp_lookup (pfile, base, pfile->buffer->cur - base);
1659@@ -1697,6 +2070,7 @@ lex_raw_string (cpp_reader *pfile, cpp_t
1660 {
1661 uchar raw_prefix[17];
1662 uchar temp_buffer[18];
1663+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1664 const uchar *orig_base;
1665 unsigned int raw_prefix_len = 0, raw_suffix_len = 0;
1666 enum raw_str_phase { RAW_STR_PREFIX, RAW_STR, RAW_STR_SUFFIX };
1667@@ -1946,8 +2320,15 @@ lex_raw_string (cpp_reader *pfile, cpp_t
1668 cur = base = pfile->buffer->cur;
1669 note = &pfile->buffer->notes[pfile->buffer->cur_note];
1670 }
1671+ else if (__builtin_expect ((unsigned char) c == bidi::utf8_start, 0)
1672+ && warn_bidi_p)
1673+ maybe_warn_bidi_on_char (pfile, pos - 1, get_bidi_utf8 (pos - 1),
1674+ /*ucn_p=*/false);
1675 }
1676
1677+ if (warn_bidi_p)
1678+ maybe_warn_bidi_on_close (pfile, pos);
1679+
1680 if (CPP_OPTION (pfile, user_literals))
1681 {
1682 /* If a string format macro, say from inttypes.h, is placed touching
1683@@ -2042,15 +2423,27 @@ lex_string (cpp_reader *pfile, cpp_token
1684 else
1685 terminator = '>', type = CPP_HEADER_NAME;
1686
1687+ const bool warn_bidi_p = pfile->warn_bidi_p ();
1688 for (;;)
1689 {
1690 cppchar_t c = *cur++;
1691
1692 /* In #include-style directives, terminators are not escapable. */
1693 if (c == '\\' && !pfile->state.angled_headers && *cur != '\n')
1694- cur++;
1695+ {
1696+ if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p)
1697+ {
1698+ bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U');
1699+ maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true);
1700+ }
1701+ cur++;
1702+ }
1703 else if (c == terminator)
1704- break;
1705+ {
1706+ if (warn_bidi_p)
1707+ maybe_warn_bidi_on_close (pfile, cur - 1);
1708+ break;
1709+ }
1710 else if (c == '\n')
1711 {
1712 cur--;
1713@@ -2067,6 +2460,11 @@ lex_string (cpp_reader *pfile, cpp_token
1714 }
1715 else if (c == '\0')
1716 saw_NUL = true;
1717+ else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
1718+ {
1719+ bidi::kind kind = get_bidi_utf8 (cur - 1);
1720+ maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false);
1721+ }
1722 }
1723
1724 if (saw_NUL && !pfile->state.skipping)
diff --git a/meta/recipes-devtools/gcc/gcc/0003-aarch64-Mitigate-SLS-for-BLR-instruction.patch b/meta/recipes-devtools/gcc/gcc/0003-aarch64-Mitigate-SLS-for-BLR-instruction.patch
deleted file mode 100644
index 716a367172..0000000000
--- a/meta/recipes-devtools/gcc/gcc/0003-aarch64-Mitigate-SLS-for-BLR-instruction.patch
+++ /dev/null
@@ -1,658 +0,0 @@
1Upstream-Status: Backport
2Signed-off-by: Ross Burton <ross.burton@arm.com>
3
4From a5e7efc40ed841934c1d913f39476afa17d8e5f7 Mon Sep 17 00:00:00 2001
5From: Matthew Malcomson <matthew.malcomson@arm.com>
6Date: Thu, 9 Jul 2020 09:11:59 +0100
7Subject: [PATCH 3/3] aarch64: Mitigate SLS for BLR instruction
8
9This patch introduces the mitigation for Straight Line Speculation past
10the BLR instruction.
11
12This mitigation replaces BLR instructions with a BL to a stub which uses
13a BR to jump to the original value. These function stubs are then
14appended with a speculation barrier to ensure no straight line
15speculation happens after these jumps.
16
17When optimising for speed we use a set of stubs for each function since
18this should help the branch predictor make more accurate predictions
19about where a stub should branch.
20
21When optimising for size we use one set of stubs for all functions.
22This set of stubs can have human readable names, and we are using
23`__call_indirect_x<N>` for register x<N>.
24
25When BTI branch protection is enabled the BLR instruction can jump to a
26`BTI c` instruction using any register, while the BR instruction can
27only jump to a `BTI c` instruction using the x16 or x17 registers.
28Hence, in order to ensure this transformation is safe we mov the value
29of the original register into x16 and use x16 for the BR.
30
31As an example when optimising for size:
32a
33 BLR x0
34instruction would get transformed to something like
35 BL __call_indirect_x0
36where __call_indirect_x0 labels a thunk that contains
37__call_indirect_x0:
38 MOV X16, X0
39 BR X16
40 <speculation barrier>
41
42The first version of this patch used local symbols specific to a
43compilation unit to try and avoid relocations.
44This was mistaken since functions coming from the same compilation unit
45can still be in different sections, and the assembler will insert
46relocations at jumps between sections.
47
48On any relocation the linker is permitted to emit a veneer to handle
49jumps between symbols that are very far apart. The registers x16 and
50x17 may be clobbered by these veneers.
51Hence the function stubs cannot rely on the values of x16 and x17 being
52the same as just before the function stub is called.
53
54Similar can be said for the hot/cold partitioning of single functions,
55so function-local stubs have the same restriction.
56
57This updated version of the patch never emits function stubs for x16 and
58x17, and instead forces other registers to be used.
59
60Given the above, there is now no benefit to local symbols (since they
61are not enough to avoid dealing with linker intricacies). This patch
62now uses global symbols with hidden visibility each stored in their own
63COMDAT section. This means stubs can be shared between compilation
64units while still avoiding the PLT indirection.
65
66This patch also removes the `__call_indirect_x30` stub (and
67function-local equivalent) which would simply jump back to the original
68location.
69
70The function-local stubs are emitted to the assembly output file in one
71chunk, which means we need not add the speculation barrier directly
72after each one.
73This is because we know for certain that the instructions directly after
74the BR in all but the last function stub will be from another one of
75these stubs and hence will not contain a speculation gadget.
76Instead we add a speculation barrier at the end of the sequence of
77stubs.
78
79The global stubs are emitted in COMDAT/.linkonce sections by
80themselves so that the linker can remove duplicates from multiple object
81files. This means they are not emitted in one chunk, and each one must
82include the speculation barrier.
83
84Another difference is that since the global stubs are shared across
85compilation units we do not know that all functions will be targeting an
86architecture supporting the SB instruction.
87Rather than provide multiple stubs for each architecture, we provide a
88stub that will work for all architectures -- using the DSB+ISB barrier.
89
90This mitigation does not apply for BLR instructions in the following
91places:
92- Some accesses to thread-local variables use a code sequence with a BLR
93 instruction. This code sequence is part of the binary interface between
94 compiler and linker. If this BLR instruction needs to be mitigated, it'd
95 probably be best to do so in the linker. It seems that the code sequence
96 for thread-local variable access is unlikely to lead to a Spectre Revalation
97 Gadget.
98- PLT stubs are produced by the linker and each contain a BLR instruction.
99 It seems that at most only after the last PLT stub a Spectre Revalation
100 Gadget might appear.
101
102Testing:
103 Bootstrap and regtest on AArch64
104 (with BOOT_CFLAGS="-mharden-sls=retbr,blr")
105 Used a temporary hack(1) in gcc-dg.exp to use these options on every
106 test in the testsuite, a slight modification to emit the speculation
107 barrier after every function stub, and a script to check that the
108 output never emitted a BLR, or unmitigated BR or RET instruction.
109 Similar on an aarch64-none-elf cross-compiler.
110
1111) Temporary hack emitted a speculation barrier at the end of every stub
112function, and used a script to ensure that:
113 a) Every RET or BR is immediately followed by a speculation barrier.
114 b) No BLR instruction is emitted by compiler.
115
116gcc/ChangeLog:
117
118 * config/aarch64/aarch64-protos.h (aarch64_indirect_call_asm):
119 New declaration.
120 * config/aarch64/aarch64.c (aarch64_regno_regclass): Handle new
121 stub registers class.
122 (aarch64_class_max_nregs): Likewise.
123 (aarch64_register_move_cost): Likewise.
124 (aarch64_sls_shared_thunks): Global array to store stub labels.
125 (aarch64_sls_emit_function_stub): New.
126 (aarch64_create_blr_label): New.
127 (aarch64_sls_emit_blr_function_thunks): New.
128 (aarch64_sls_emit_shared_blr_thunks): New.
129 (aarch64_asm_file_end): New.
130 (aarch64_indirect_call_asm): New.
131 (TARGET_ASM_FILE_END): Use aarch64_asm_file_end.
132 (TARGET_ASM_FUNCTION_EPILOGUE): Use
133 aarch64_sls_emit_blr_function_thunks.
134 * config/aarch64/aarch64.h (STB_REGNUM_P): New.
135 (enum reg_class): Add STUB_REGS class.
136 (machine_function): Introduce `call_via` array for
137 function-local stub labels.
138 * config/aarch64/aarch64.md (*call_insn, *call_value_insn): Use
139 aarch64_indirect_call_asm to emit code when hardening BLR
140 instructions.
141 * config/aarch64/constraints.md (Ucr): New constraint
142 representing registers for indirect calls. Is GENERAL_REGS
143 usually, and STUB_REGS when hardening BLR instruction against
144 SLS.
145 * config/aarch64/predicates.md (aarch64_general_reg): STUB_REGS class
146 is also a general register.
147
148gcc/testsuite/ChangeLog:
149
150 * gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c: New test.
151 * gcc.target/aarch64/sls-mitigation/sls-miti-blr.c: New test.
152---
153 gcc/config/aarch64/aarch64-protos.h | 1 +
154 gcc/config/aarch64/aarch64.c | 225 ++++++++++++++++++++-
155 gcc/config/aarch64/aarch64.h | 15 ++
156 gcc/config/aarch64/aarch64.md | 11 +-
157 gcc/config/aarch64/constraints.md | 9 +
158 gcc/config/aarch64/predicates.md | 3 +-
159 .../aarch64/sls-mitigation/sls-miti-blr-bti.c | 40 ++++
160 .../aarch64/sls-mitigation/sls-miti-blr.c | 33 +++
161 8 files changed, 328 insertions(+), 9 deletions(-)
162 create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c
163 create mode 100644 gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr.c
164
165diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
166index ee0ffde..839f801 100644
167--- a/gcc/config/aarch64/aarch64-protos.h
168+++ b/gcc/config/aarch64/aarch64-protos.h
169@@ -782,6 +782,7 @@ extern const atomic_ool_names aarch64_ool_ldeor_names;
170 tree aarch64_resolve_overloaded_builtin_general (location_t, tree, void *);
171
172 const char *aarch64_sls_barrier (int);
173+const char *aarch64_indirect_call_asm (rtx);
174 extern bool aarch64_harden_sls_retbr_p (void);
175 extern bool aarch64_harden_sls_blr_p (void);
176
177diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
178index 2389d49..0f7bba3 100644
179--- a/gcc/config/aarch64/aarch64.c
180+++ b/gcc/config/aarch64/aarch64.c
181@@ -10605,6 +10605,9 @@ aarch64_label_mentioned_p (rtx x)
182 enum reg_class
183 aarch64_regno_regclass (unsigned regno)
184 {
185+ if (STUB_REGNUM_P (regno))
186+ return STUB_REGS;
187+
188 if (GP_REGNUM_P (regno))
189 return GENERAL_REGS;
190
191@@ -10939,6 +10942,7 @@ aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode)
192 unsigned int nregs, vec_flags;
193 switch (regclass)
194 {
195+ case STUB_REGS:
196 case TAILCALL_ADDR_REGS:
197 case POINTER_REGS:
198 case GENERAL_REGS:
199@@ -13155,10 +13159,12 @@ aarch64_register_move_cost (machine_mode mode,
200 = aarch64_tune_params.regmove_cost;
201
202 /* Caller save and pointer regs are equivalent to GENERAL_REGS. */
203- if (to == TAILCALL_ADDR_REGS || to == POINTER_REGS)
204+ if (to == TAILCALL_ADDR_REGS || to == POINTER_REGS
205+ || to == STUB_REGS)
206 to = GENERAL_REGS;
207
208- if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS)
209+ if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS
210+ || from == STUB_REGS)
211 from = GENERAL_REGS;
212
213 /* Make RDFFR very expensive. In particular, if we know that the FFR
214@@ -22957,6 +22963,215 @@ aarch64_sls_barrier (int mitigation_required)
215 : "";
216 }
217
218+static GTY (()) tree aarch64_sls_shared_thunks[30];
219+static GTY (()) bool aarch64_sls_shared_thunks_needed = false;
220+const char *indirect_symbol_names[30] = {
221+ "__call_indirect_x0",
222+ "__call_indirect_x1",
223+ "__call_indirect_x2",
224+ "__call_indirect_x3",
225+ "__call_indirect_x4",
226+ "__call_indirect_x5",
227+ "__call_indirect_x6",
228+ "__call_indirect_x7",
229+ "__call_indirect_x8",
230+ "__call_indirect_x9",
231+ "__call_indirect_x10",
232+ "__call_indirect_x11",
233+ "__call_indirect_x12",
234+ "__call_indirect_x13",
235+ "__call_indirect_x14",
236+ "__call_indirect_x15",
237+ "", /* "__call_indirect_x16", */
238+ "", /* "__call_indirect_x17", */
239+ "__call_indirect_x18",
240+ "__call_indirect_x19",
241+ "__call_indirect_x20",
242+ "__call_indirect_x21",
243+ "__call_indirect_x22",
244+ "__call_indirect_x23",
245+ "__call_indirect_x24",
246+ "__call_indirect_x25",
247+ "__call_indirect_x26",
248+ "__call_indirect_x27",
249+ "__call_indirect_x28",
250+ "__call_indirect_x29",
251+};
252+
253+/* Function to create a BLR thunk. This thunk is used to mitigate straight
254+ line speculation. Instead of a simple BLR that can be speculated past,
255+ we emit a BL to this thunk, and this thunk contains a BR to the relevant
256+ register. These thunks have the relevant speculation barries put after
257+ their indirect branch so that speculation is blocked.
258+
259+ We use such a thunk so the speculation barriers are kept off the
260+ architecturally executed path in order to reduce the performance overhead.
261+
262+ When optimizing for size we use stubs shared by the linked object.
263+ When optimizing for performance we emit stubs for each function in the hope
264+ that the branch predictor can better train on jumps specific for a given
265+ function. */
266+rtx
267+aarch64_sls_create_blr_label (int regnum)
268+{
269+ gcc_assert (STUB_REGNUM_P (regnum));
270+ if (optimize_function_for_size_p (cfun))
271+ {
272+ /* For the thunks shared between different functions in this compilation
273+ unit we use a named symbol -- this is just for users to more easily
274+ understand the generated assembly. */
275+ aarch64_sls_shared_thunks_needed = true;
276+ const char *thunk_name = indirect_symbol_names[regnum];
277+ if (aarch64_sls_shared_thunks[regnum] == NULL)
278+ {
279+ /* Build a decl representing this function stub and record it for
280+ later. We build a decl here so we can use the GCC machinery for
281+ handling sections automatically (through `get_named_section` and
282+ `make_decl_one_only`). That saves us a lot of trouble handling
283+ the specifics of different output file formats. */
284+ tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
285+ get_identifier (thunk_name),
286+ build_function_type_list (void_type_node,
287+ NULL_TREE));
288+ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
289+ NULL_TREE, void_type_node);
290+ TREE_PUBLIC (decl) = 1;
291+ TREE_STATIC (decl) = 1;
292+ DECL_IGNORED_P (decl) = 1;
293+ DECL_ARTIFICIAL (decl) = 1;
294+ make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
295+ resolve_unique_section (decl, 0, false);
296+ aarch64_sls_shared_thunks[regnum] = decl;
297+ }
298+
299+ return gen_rtx_SYMBOL_REF (Pmode, thunk_name);
300+ }
301+
302+ if (cfun->machine->call_via[regnum] == NULL)
303+ cfun->machine->call_via[regnum]
304+ = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ());
305+ return cfun->machine->call_via[regnum];
306+}
307+
308+/* Helper function for aarch64_sls_emit_blr_function_thunks and
309+ aarch64_sls_emit_shared_blr_thunks below. */
310+static void
311+aarch64_sls_emit_function_stub (FILE *out_file, int regnum)
312+{
313+ /* Save in x16 and branch to that function so this transformation does
314+ not prevent jumping to `BTI c` instructions. */
315+ asm_fprintf (out_file, "\tmov\tx16, x%d\n", regnum);
316+ asm_fprintf (out_file, "\tbr\tx16\n");
317+}
318+
319+/* Emit all BLR stubs for this particular function.
320+ Here we emit all the BLR stubs needed for the current function. Since we
321+ emit these stubs in a consecutive block we know there will be no speculation
322+ gadgets between each stub, and hence we only emit a speculation barrier at
323+ the end of the stub sequences.
324+
325+ This is called in the TARGET_ASM_FUNCTION_EPILOGUE hook. */
326+void
327+aarch64_sls_emit_blr_function_thunks (FILE *out_file)
328+{
329+ if (! aarch64_harden_sls_blr_p ())
330+ return;
331+
332+ bool any_functions_emitted = false;
333+ /* We must save and restore the current function section since this assembly
334+ is emitted at the end of the function. This means it can be emitted *just
335+ after* the cold section of a function. That cold part would be emitted in
336+ a different section. That switch would trigger a `.cfi_endproc` directive
337+ to be emitted in the original section and a `.cfi_startproc` directive to
338+ be emitted in the new section. Switching to the original section without
339+ restoring would mean that the `.cfi_endproc` emitted as a function ends
340+ would happen in a different section -- leaving an unmatched
341+ `.cfi_startproc` in the cold text section and an unmatched `.cfi_endproc`
342+ in the standard text section. */
343+ section *save_text_section = in_section;
344+ switch_to_section (function_section (current_function_decl));
345+ for (int regnum = 0; regnum < 30; ++regnum)
346+ {
347+ rtx specu_label = cfun->machine->call_via[regnum];
348+ if (specu_label == NULL)
349+ continue;
350+
351+ targetm.asm_out.print_operand (out_file, specu_label, 0);
352+ asm_fprintf (out_file, ":\n");
353+ aarch64_sls_emit_function_stub (out_file, regnum);
354+ any_functions_emitted = true;
355+ }
356+ if (any_functions_emitted)
357+ /* Can use the SB if needs be here, since this stub will only be used
358+ by the current function, and hence for the current target. */
359+ asm_fprintf (out_file, "\t%s\n", aarch64_sls_barrier (true));
360+ switch_to_section (save_text_section);
361+}
362+
363+/* Emit shared BLR stubs for the current compilation unit.
364+ Over the course of compiling this unit we may have converted some BLR
365+ instructions to a BL to a shared stub function. This is where we emit those
366+ stub functions.
367+ This function is for the stubs shared between different functions in this
368+ compilation unit. We share when optimizing for size instead of speed.
369+
370+ This function is called through the TARGET_ASM_FILE_END hook. */
371+void
372+aarch64_sls_emit_shared_blr_thunks (FILE *out_file)
373+{
374+ if (! aarch64_sls_shared_thunks_needed)
375+ return;
376+
377+ for (int regnum = 0; regnum < 30; ++regnum)
378+ {
379+ tree decl = aarch64_sls_shared_thunks[regnum];
380+ if (!decl)
381+ continue;
382+
383+ const char *name = indirect_symbol_names[regnum];
384+ switch_to_section (get_named_section (decl, NULL, 0));
385+ ASM_OUTPUT_ALIGN (out_file, 2);
386+ targetm.asm_out.globalize_label (out_file, name);
387+ /* Only emits if the compiler is configured for an assembler that can
388+ handle visibility directives. */
389+ targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
390+ ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function");
391+ ASM_OUTPUT_LABEL (out_file, name);
392+ aarch64_sls_emit_function_stub (out_file, regnum);
393+ /* Use the most conservative target to ensure it can always be used by any
394+ function in the translation unit. */
395+ asm_fprintf (out_file, "\tdsb\tsy\n\tisb\n");
396+ ASM_DECLARE_FUNCTION_SIZE (out_file, name, decl);
397+ }
398+}
399+
400+/* Implement TARGET_ASM_FILE_END. */
401+void
402+aarch64_asm_file_end ()
403+{
404+ aarch64_sls_emit_shared_blr_thunks (asm_out_file);
405+ /* Since this function will be called for the ASM_FILE_END hook, we ensure
406+ that what would be called otherwise (e.g. `file_end_indicate_exec_stack`
407+ for FreeBSD) still gets called. */
408+#ifdef TARGET_ASM_FILE_END
409+ TARGET_ASM_FILE_END ();
410+#endif
411+}
412+
413+const char *
414+aarch64_indirect_call_asm (rtx addr)
415+{
416+ gcc_assert (REG_P (addr));
417+ if (aarch64_harden_sls_blr_p ())
418+ {
419+ rtx stub_label = aarch64_sls_create_blr_label (REGNO (addr));
420+ output_asm_insn ("bl\t%0", &stub_label);
421+ }
422+ else
423+ output_asm_insn ("blr\t%0", &addr);
424+ return "";
425+}
426+
427 /* Target-specific selftests. */
428
429 #if CHECKING_P
430@@ -23507,6 +23722,12 @@ aarch64_libgcc_floating_mode_supported_p
431 #undef TARGET_MD_ASM_ADJUST
432 #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
433
434+#undef TARGET_ASM_FILE_END
435+#define TARGET_ASM_FILE_END aarch64_asm_file_end
436+
437+#undef TARGET_ASM_FUNCTION_EPILOGUE
438+#define TARGET_ASM_FUNCTION_EPILOGUE aarch64_sls_emit_blr_function_thunks
439+
440 struct gcc_target targetm = TARGET_INITIALIZER;
441
442 #include "gt-aarch64.h"
443diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
444index 8e0fc37..7331450 100644
445--- a/gcc/config/aarch64/aarch64.h
446+++ b/gcc/config/aarch64/aarch64.h
447@@ -643,6 +643,16 @@ extern unsigned aarch64_architecture_version;
448 #define GP_REGNUM_P(REGNO) \
449 (((unsigned) (REGNO - R0_REGNUM)) <= (R30_REGNUM - R0_REGNUM))
450
451+/* Registers known to be preserved over a BL instruction. This consists of the
452+ GENERAL_REGS without x16, x17, and x30. The x30 register is changed by the
453+ BL instruction itself, while the x16 and x17 registers may be used by
454+ veneers which can be inserted by the linker. */
455+#define STUB_REGNUM_P(REGNO) \
456+ (GP_REGNUM_P (REGNO) \
457+ && (REGNO) != R16_REGNUM \
458+ && (REGNO) != R17_REGNUM \
459+ && (REGNO) != R30_REGNUM) \
460+
461 #define FP_REGNUM_P(REGNO) \
462 (((unsigned) (REGNO - V0_REGNUM)) <= (V31_REGNUM - V0_REGNUM))
463
464@@ -667,6 +677,7 @@ enum reg_class
465 {
466 NO_REGS,
467 TAILCALL_ADDR_REGS,
468+ STUB_REGS,
469 GENERAL_REGS,
470 STACK_REG,
471 POINTER_REGS,
472@@ -689,6 +700,7 @@ enum reg_class
473 { \
474 "NO_REGS", \
475 "TAILCALL_ADDR_REGS", \
476+ "STUB_REGS", \
477 "GENERAL_REGS", \
478 "STACK_REG", \
479 "POINTER_REGS", \
480@@ -708,6 +720,7 @@ enum reg_class
481 { \
482 { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
483 { 0x00030000, 0x00000000, 0x00000000 }, /* TAILCALL_ADDR_REGS */\
484+ { 0x3ffcffff, 0x00000000, 0x00000000 }, /* STUB_REGS */ \
485 { 0x7fffffff, 0x00000000, 0x00000003 }, /* GENERAL_REGS */ \
486 { 0x80000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
487 { 0xffffffff, 0x00000000, 0x00000003 }, /* POINTER_REGS */ \
488@@ -862,6 +875,8 @@ typedef struct GTY (()) machine_function
489 struct aarch64_frame frame;
490 /* One entry for each hard register. */
491 bool reg_is_wrapped_separately[LAST_SAVED_REGNUM];
492+ /* One entry for each general purpose register. */
493+ rtx call_via[SP_REGNUM];
494 bool label_is_assembled;
495 } machine_function;
496 #endif
497diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
498index dda04ee..43da754 100644
499--- a/gcc/config/aarch64/aarch64.md
500+++ b/gcc/config/aarch64/aarch64.md
501@@ -1022,16 +1022,15 @@
502 )
503
504 (define_insn "*call_insn"
505- [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "r, Usf"))
506+ [(call (mem:DI (match_operand:DI 0 "aarch64_call_insn_operand" "Ucr, Usf"))
507 (match_operand 1 "" ""))
508 (unspec:DI [(match_operand:DI 2 "const_int_operand")] UNSPEC_CALLEE_ABI)
509 (clobber (reg:DI LR_REGNUM))]
510 ""
511 "@
512- blr\\t%0
513+ * return aarch64_indirect_call_asm (operands[0]);
514 bl\\t%c0"
515- [(set_attr "type" "call, call")]
516-)
517+ [(set_attr "type" "call, call")])
518
519 (define_expand "call_value"
520 [(parallel
521@@ -1050,13 +1049,13 @@
522
523 (define_insn "*call_value_insn"
524 [(set (match_operand 0 "" "")
525- (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "r, Usf"))
526+ (call (mem:DI (match_operand:DI 1 "aarch64_call_insn_operand" "Ucr, Usf"))
527 (match_operand 2 "" "")))
528 (unspec:DI [(match_operand:DI 3 "const_int_operand")] UNSPEC_CALLEE_ABI)
529 (clobber (reg:DI LR_REGNUM))]
530 ""
531 "@
532- blr\\t%1
533+ * return aarch64_indirect_call_asm (operands[1]);
534 bl\\t%c1"
535 [(set_attr "type" "call, call")]
536 )
537diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
538index d993268..8cc6f50 100644
539--- a/gcc/config/aarch64/constraints.md
540+++ b/gcc/config/aarch64/constraints.md
541@@ -24,6 +24,15 @@
542 (define_register_constraint "Ucs" "TAILCALL_ADDR_REGS"
543 "@internal Registers suitable for an indirect tail call")
544
545+(define_register_constraint "Ucr"
546+ "aarch64_harden_sls_blr_p () ? STUB_REGS : GENERAL_REGS"
547+ "@internal Registers to be used for an indirect call.
548+ This is usually the general registers, but when we are hardening against
549+ Straight Line Speculation we disallow x16, x17, and x30 so we can use
550+ indirection stubs. These indirection stubs cannot use the above registers
551+ since they will be reached by a BL that may have to go through a linker
552+ veneer.")
553+
554 (define_register_constraint "w" "FP_REGS"
555 "Floating point and SIMD vector registers.")
556
557diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md
558index 215fcec..1754b1e 100644
559--- a/gcc/config/aarch64/predicates.md
560+++ b/gcc/config/aarch64/predicates.md
561@@ -32,7 +32,8 @@
562
563 (define_predicate "aarch64_general_reg"
564 (and (match_operand 0 "register_operand")
565- (match_test "REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS")))
566+ (match_test "REGNO_REG_CLASS (REGNO (op)) == STUB_REGS
567+ || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS")))
568
569 ;; Return true if OP a (const_int 0) operand.
570 (define_predicate "const0_operand"
571diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c
572new file mode 100644
573index 0000000..b1fb754
574--- /dev/null
575+++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr-bti.c
576@@ -0,0 +1,40 @@
577+/* { dg-do compile } */
578+/* { dg-additional-options "-mharden-sls=blr -mbranch-protection=bti" } */
579+/*
580+ Ensure that the SLS hardening of BLR leaves no BLR instructions.
581+ Here we also check that there are no BR instructions with anything except an
582+ x16 or x17 register. This is because a `BTI c` instruction can be branched
583+ to using a BLR instruction using any register, but can only be branched to
584+ with a BR using an x16 or x17 register.
585+ */
586+typedef int (foo) (int, int);
587+typedef void (bar) (int, int);
588+struct sls_testclass {
589+ foo *x;
590+ bar *y;
591+ int left;
592+ int right;
593+};
594+
595+/* We test both RTL patterns for a call which returns a value and a call which
596+ does not. */
597+int blr_call_value (struct sls_testclass x)
598+{
599+ int retval = x.x(x.left, x.right);
600+ if (retval % 10)
601+ return 100;
602+ return 9;
603+}
604+
605+int blr_call (struct sls_testclass x)
606+{
607+ x.y(x.left, x.right);
608+ if (x.left % 10)
609+ return 100;
610+ return 9;
611+}
612+
613+/* { dg-final { scan-assembler-not {\tblr\t} } } */
614+/* { dg-final { scan-assembler-not {\tbr\tx(?!16|17)} } } */
615+/* { dg-final { scan-assembler {\tbr\tx(16|17)} } } */
616+
617diff --git a/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr.c b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr.c
618new file mode 100644
619index 0000000..88bafff
620--- /dev/null
621+++ b/gcc/testsuite/gcc.target/aarch64/sls-mitigation/sls-miti-blr.c
622@@ -0,0 +1,33 @@
623+/* { dg-additional-options "-mharden-sls=blr -save-temps" } */
624+/* Ensure that the SLS hardening of BLR leaves no BLR instructions.
625+ We only test that all BLR instructions have been removed, not that the
626+ resulting code makes sense. */
627+typedef int (foo) (int, int);
628+typedef void (bar) (int, int);
629+struct sls_testclass {
630+ foo *x;
631+ bar *y;
632+ int left;
633+ int right;
634+};
635+
636+/* We test both RTL patterns for a call which returns a value and a call which
637+ does not. */
638+int blr_call_value (struct sls_testclass x)
639+{
640+ int retval = x.x(x.left, x.right);
641+ if (retval % 10)
642+ return 100;
643+ return 9;
644+}
645+
646+int blr_call (struct sls_testclass x)
647+{
648+ x.y(x.left, x.right);
649+ if (x.left % 10)
650+ return 100;
651+ return 9;
652+}
653+
654+/* { dg-final { scan-assembler-not {\tblr\t} } } */
655+/* { dg-final { scan-assembler {\tbr\tx[0-9][0-9]?} } } */
656--
6572.7.4
658
diff --git a/meta/recipes-devtools/gcc/gcc/0004-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0004-CVE-2021-42574.patch
new file mode 100644
index 0000000000..877b8a6452
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0004-CVE-2021-42574.patch
@@ -0,0 +1,138 @@
1From 1a7f2c0774129750fdf73e9f1b78f0ce983c9ab3 Mon Sep 17 00:00:00 2001
2From: David Malcolm <dmalcolm@redhat.com>
3Date: Tue, 2 Nov 2021 09:54:32 -0400
4Subject: [PATCH] libcpp: escape non-ASCII source bytes in -Wbidi-chars=
5 [PR103026]
6MIME-Version: 1.0
7Content-Type: text/plain; charset=utf8
8Content-Transfer-Encoding: 8bit
9
10This flags rich_locations associated with -Wbidi-chars= so that
11non-ASCII bytes will be escaped when printing the source lines
12(using the diagnostics support I added in
13r12-4825-gbd5e882cf6e0def3dd1bc106075d59a303fe0d1e).
14
15In particular, this ensures that the printed source lines will
16be pure ASCII, and thus the visual ordering of the characters
17will be the same as the logical ordering.
18
19Before:
20
21 Wbidi-chars-1.c: In function âmainâ:
22 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
23 6 | /*â® } â¦if (isAdmin)⩠⦠begin admins only */
24 | ^
25 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
26 9 | /* end admins only â® { â¦*/
27 | ^
28
29 Wbidi-chars-11.c:6:15: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
30 6 | int LRE_âª_PDF_\u202c;
31 | ^
32 Wbidi-chars-11.c:8:19: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
33 8 | int LRE_\u202a_PDF_â¬_;
34 | ^
35 Wbidi-chars-11.c:10:28: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
36 10 | const char *s1 = "LRE_âª_PDF_\u202c";
37 | ^
38 Wbidi-chars-11.c:12:33: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
39 12 | const char *s2 = "LRE_\u202a_PDF_â¬";
40 | ^
41
42After:
43
44 Wbidi-chars-1.c: In function âmainâ:
45 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
46 6 | /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
47 | ^
48 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
49 9 | /* end admins only <U+202E> { <U+2066>*/
50 | ^
51
52 Wbidi-chars-11.c:6:15: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
53 6 | int LRE_<U+202A>_PDF_\u202c;
54 | ^
55 Wbidi-chars-11.c:8:19: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
56 8 | int LRE_\u202a_PDF_<U+202C>_;
57 | ^
58 Wbidi-chars-11.c:10:28: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
59 10 | const char *s1 = "LRE_<U+202A>_PDF_\u202c";
60 | ^
61 Wbidi-chars-11.c:12:33: warning: UTF-8 vs UCN mismatch when closing a context by "U+202C (POP DIRECTIONAL FORMATTING)" [-Wbidi-chars=]
62 12 | const char *s2 = "LRE_\u202a_PDF_<U+202C>";
63 | ^
64
65libcpp/ChangeLog:
66 PR preprocessor/103026
67 * lex.c (maybe_warn_bidi_on_close): Use a rich_location
68 and call set_escape_on_output (true) on it.
69 (maybe_warn_bidi_on_char): Likewise.
70
71Signed-off-by: David Malcolm <dmalcolm@redhat.com>
72
73CVE: CVE-2021-42574
74Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=1a7f2c0774129750fdf73e9f1b78f0ce983c9ab3]
75Signed-off-by: Pgowda <pgowda.cve@gmail.com>
76
77---
78 libcpp/lex.c | 29 +++++++++++++++++------------
79 1 file changed, 17 insertions(+), 12 deletions(-)
80
81diff --git a/libcpp/lex.c b/libcpp/lex.c
82--- a/libcpp/lex.c 2021-12-14 20:44:11.647815287 -0800
83+++ b/libcpp/lex.c 2021-12-14 20:43:38.008383220 -0800
84@@ -1427,9 +1427,11 @@ maybe_warn_bidi_on_close (cpp_reader *pf
85 const location_t loc
86 = linemap_position_for_column (pfile->line_table,
87 CPP_BUF_COLUMN (pfile->buffer, p));
88- cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
89- "unpaired UTF-8 bidirectional control character "
90- "detected");
91+ rich_location rich_loc (pfile->line_table, loc);
92+ rich_loc.set_escape_on_output (true);
93+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
94+ "unpaired UTF-8 bidirectional control character "
95+ "detected");
96 }
97 /* We're done with this context. */
98 bidi::on_close ();
99@@ -1454,6 +1456,9 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
100 const location_t loc
101 = linemap_position_for_column (pfile->line_table,
102 CPP_BUF_COLUMN (pfile->buffer, p));
103+ rich_location rich_loc (pfile->line_table, loc);
104+ rich_loc.set_escape_on_output (true);
105+
106 /* It seems excessive to warn about a PDI/PDF that is closing
107 an opened context because we've already warned about the
108 opening character. Except warn when we have a UCN x UTF-8
109@@ -1462,20 +1467,20 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
110 {
111 if (warn_bidi == bidirectional_unpaired
112 && bidi::current_ctx_ucn_p () != ucn_p)
113- cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
114- "UTF-8 vs UCN mismatch when closing "
115- "a context by \"%s\"", bidi::to_str (kind));
116+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
117+ "UTF-8 vs UCN mismatch when closing "
118+ "a context by \"%s\"", bidi::to_str (kind));
119 }
120 else if (warn_bidi == bidirectional_any)
121 {
122 if (kind == bidi::kind::PDF || kind == bidi::kind::PDI)
123- cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
124- "\"%s\" is closing an unopened context",
125- bidi::to_str (kind));
126+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
127+ "\"%s\" is closing an unopened context",
128+ bidi::to_str (kind));
129 else
130- cpp_warning_with_line (pfile, CPP_W_BIDIRECTIONAL, loc, 0,
131- "found problematic Unicode character \"%s\"",
132- bidi::to_str (kind));
133+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
134+ "found problematic Unicode character \"%s\"",
135+ bidi::to_str (kind));
136 }
137 }
138 /* We're done with this context. */
diff --git a/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch b/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch
new file mode 100644
index 0000000000..6e983a67b6
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc/0005-CVE-2021-42574.patch
@@ -0,0 +1,575 @@
1From bef32d4a28595e933f24fef378cf052a30b674a7 Mon Sep 17 00:00:00 2001
2From: David Malcolm <dmalcolm@redhat.com>
3Date: Tue, 2 Nov 2021 15:45:22 -0400
4Subject: [PATCH] libcpp: capture and underline ranges in -Wbidi-chars=
5 [PR103026]
6MIME-Version: 1.0
7Content-Type: text/plain; charset=utf8
8Content-Transfer-Encoding: 8bit
9
10This patch converts the bidi::vec to use a struct so that we can
11capture location_t values for the bidirectional control characters.
12
13Before:
14
15 Wbidi-chars-1.c: In function âmainâ:
16 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
17 6 | /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
18 | ^
19 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control character detected [-Wbidi-chars=]
20 9 | /* end admins only <U+202E> { <U+2066>*/
21 | ^
22
23After:
24
25 Wbidi-chars-1.c: In function âmainâ:
26 Wbidi-chars-1.c:6:43: warning: unpaired UTF-8 bidirectional control characters detected [-Wbidi-chars=]
27 6 | /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
28 | ~~~~~~~~ ~~~~~~~~ ^
29 | | | |
30 | | | end of bidirectional context
31 | U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)
32 Wbidi-chars-1.c:9:28: warning: unpaired UTF-8 bidirectional control characters detected [-Wbidi-chars=]
33 9 | /* end admins only <U+202E> { <U+2066>*/
34 | ~~~~~~~~ ~~~~~~~~ ^
35 | | | |
36 | | | end of bidirectional context
37 | | U+2066 (LEFT-TO-RIGHT ISOLATE)
38 | U+202E (RIGHT-TO-LEFT OVERRIDE)
39
40Signed-off-by: David Malcolm <dmalcolm@redhat.com>
41
42gcc/testsuite/ChangeLog:
43 PR preprocessor/103026
44 * c-c++-common/Wbidi-chars-ranges.c: New test.
45
46libcpp/ChangeLog:
47 PR preprocessor/103026
48 * lex.c (struct bidi::context): New.
49 (bidi::vec): Convert to a vec of context rather than unsigned
50 char.
51 (bidi::ctx_at): Rename to...
52 (bidi::pop_kind_at): ...this and reimplement for above change.
53 (bidi::current_ctx): Update for change to vec.
54 (bidi::current_ctx_ucn_p): Likewise.
55 (bidi::current_ctx_loc): New.
56 (bidi::on_char): Update for usage of context struct. Add "loc"
57 param and pass it when pushing contexts.
58 (get_location_for_byte_range_in_cur_line): New.
59 (get_bidi_utf8): Rename to...
60 (get_bidi_utf8_1): ...this, reintroducing...
61 (get_bidi_utf8): ...as a wrapper, setting *OUT when the result is
62 not NONE.
63 (get_bidi_ucn): Rename to...
64 (get_bidi_ucn_1): ...this, reintroducing...
65 (get_bidi_ucn): ...as a wrapper, setting *OUT when the result is
66 not NONE.
67 (class unpaired_bidi_rich_location): New.
68 (maybe_warn_bidi_on_close): Use unpaired_bidi_rich_location when
69 reporting on unpaired bidi chars. Split into singular vs plural
70 spellings.
71 (maybe_warn_bidi_on_char): Pass in a location_t rather than a
72 const uchar * and use it when emitting warnings, and when calling
73 bidi::on_char.
74 (_cpp_skip_block_comment): Capture location when kind is not NONE
75 and pass it to maybe_warn_bidi_on_char.
76 (skip_line_comment): Likewise.
77 (forms_identifier_p): Likewise.
78 (lex_raw_string): Likewise.
79 (lex_string): Likewise.
80
81Signed-off-by: David Malcolm <dmalcolm@redhat.com>
82
83CVE: CVE-2021-42574
84Upstream-Status: Backport [https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=bef32d4a28595e933f24fef378cf052a30b674a7]
85Signed-off-by: Pgowda <pgowda.cve@gmail.com>
86
87---
88 .../c-c++-common/Wbidi-chars-ranges.c | 54 ++++
89 libcpp/lex.c | 251 ++++++++++++++----
90 2 files changed, 257 insertions(+), 48 deletions(-)
91 create mode 100644 gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
92
93diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
94--- a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c 1969-12-31 16:00:00.000000000 -0800
95+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c 2021-12-25 01:39:55.116281847 -0800
96@@ -0,0 +1,54 @@
97+/* PR preprocessor/103026 */
98+/* { dg-do compile } */
99+/* { dg-options "-Wbidi-chars=unpaired -fdiagnostics-show-caret" } */
100+/* Verify that we escape and underline pertinent bidirectional
101+ control characters when quoting the source. */
102+
103+int test_unpaired_bidi () {
104+ int isAdmin = 0;
105+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */
106+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
107+#if 0
108+ { dg-begin-multiline-output "" }
109+ /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
110+ ~~~~~~~~ ~~~~~~~~ ^
111+ | | |
112+ | | end of bidirectional context
113+ U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)
114+ { dg-end-multiline-output "" }
115+#endif
116+
117+ __builtin_printf("You are an admin.\n");
118+ /* end admins only ‮ { ⁦*/
119+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
120+#if 0
121+ { dg-begin-multiline-output "" }
122+ /* end admins only <U+202E> { <U+2066>*/
123+ ~~~~~~~~ ~~~~~~~~ ^
124+ | | |
125+ | | end of bidirectional context
126+ | U+2066 (LEFT-TO-RIGHT ISOLATE)
127+ U+202E (RIGHT-TO-LEFT OVERRIDE)
128+ { dg-end-multiline-output "" }
129+#endif
130+
131+ return 0;
132+}
133+
134+int LRE_‪_PDF_\u202c;
135+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
136+#if 0
137+ { dg-begin-multiline-output "" }
138+ int LRE_<U+202A>_PDF_\u202c;
139+ ~~~~~~~~ ^~~~~~
140+ { dg-end-multiline-output "" }
141+#endif
142+
143+const char *s1 = "LRE_‪_PDF_\u202c";
144+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
145+#if 0
146+ { dg-begin-multiline-output "" }
147+ const char *s1 = "LRE_<U+202A>_PDF_\u202c";
148+ ~~~~~~~~ ^~~~~~
149+ { dg-end-multiline-output "" }
150+#endif
151diff --git a/libcpp/lex.c b/libcpp/lex.c
152--- a/libcpp/lex.c 2021-12-25 01:41:16.522868808 -0800
153+++ b/libcpp/lex.c 2021-12-25 06:28:58.530680302 -0800
154@@ -1172,11 +1172,34 @@ namespace bidi {
155 /* All the UTF-8 encodings of bidi characters start with E2. */
156 constexpr uchar utf8_start = 0xe2;
157
158+ struct context
159+ {
160+ context () {}
161+ context (location_t loc, kind k, bool pdf, bool ucn)
162+ : m_loc (loc), m_kind (k), m_pdf (pdf), m_ucn (ucn)
163+ {
164+ }
165+
166+ kind get_pop_kind () const
167+ {
168+ return m_pdf ? kind::PDF : kind::PDI;
169+ }
170+ bool ucn_p () const
171+ {
172+ return m_ucn;
173+ }
174+
175+ location_t m_loc;
176+ kind m_kind;
177+ unsigned m_pdf : 1;
178+ unsigned m_ucn : 1;
179+ };
180+
181 /* A vector holding currently open bidi contexts. We use a char for
182 each context, its LSB is 1 if it represents a PDF context, 0 if it
183 represents a PDI context. The next bit is 1 if this context was open
184 by a bidi character written as a UCN, and 0 when it was UTF-8. */
185- semi_embedded_vec <unsigned char, 16> vec;
186+ semi_embedded_vec <context, 16> vec;
187
188 /* Close the whole comment/identifier/string literal/character constant
189 context. */
190@@ -1193,19 +1216,19 @@ namespace bidi {
191 vec.truncate (len - 1);
192 }
193
194- /* Return the context of the Ith element. */
195- kind ctx_at (unsigned int i)
196+ /* Return the pop kind of the context of the Ith element. */
197+ kind pop_kind_at (unsigned int i)
198 {
199- return (vec[i] & 1) ? kind::PDF : kind::PDI;
200+ return vec[i].get_pop_kind ();
201 }
202
203- /* Return which context is currently opened. */
204+ /* Return the pop kind of the context that is currently opened. */
205 kind current_ctx ()
206 {
207 unsigned int len = vec.count ();
208 if (len == 0)
209 return kind::NONE;
210- return ctx_at (len - 1);
211+ return vec[len - 1].get_pop_kind ();
212 }
213
214 /* Return true if the current context comes from a UCN origin, that is,
215@@ -1214,11 +1237,19 @@ namespace bidi {
216 {
217 unsigned int len = vec.count ();
218 gcc_checking_assert (len > 0);
219- return (vec[len - 1] >> 1) & 1;
220+ return vec[len - 1].m_ucn;
221 }
222
223- /* We've read a bidi char, update the current vector as necessary. */
224- void on_char (kind k, bool ucn_p)
225+ location_t current_ctx_loc ()
226+ {
227+ unsigned int len = vec.count ();
228+ gcc_checking_assert (len > 0);
229+ return vec[len - 1].m_loc;
230+ }
231+
232+ /* We've read a bidi char, update the current vector as necessary.
233+ LOC is only valid when K is not kind::NONE. */
234+ void on_char (kind k, bool ucn_p, location_t loc)
235 {
236 switch (k)
237 {
238@@ -1226,12 +1257,12 @@ namespace bidi {
239 case kind::RLE:
240 case kind::LRO:
241 case kind::RLO:
242- vec.push (ucn_p ? 3u : 1u);
243+ vec.push (context (loc, k, true, ucn_p));
244 break;
245 case kind::LRI:
246 case kind::RLI:
247 case kind::FSI:
248- vec.push (ucn_p ? 2u : 0u);
249+ vec.push (context (loc, k, false, ucn_p));
250 break;
251 /* PDF terminates the scope of the last LRE, RLE, LRO, or RLO
252 whose scope has not yet been terminated. */
253@@ -1245,7 +1276,7 @@ namespace bidi {
254 yet been terminated. */
255 case kind::PDI:
256 for (int i = vec.count () - 1; i >= 0; --i)
257- if (ctx_at (i) == kind::PDI)
258+ if (pop_kind_at (i) == kind::PDI)
259 {
260 vec.truncate (i);
261 break;
262@@ -1295,10 +1326,47 @@ namespace bidi {
263 }
264 }
265
266+/* Get location_t for the range of bytes [START, START + NUM_BYTES)
267+ within the current line in FILE, with the caret at START. */
268+
269+static location_t
270+get_location_for_byte_range_in_cur_line (cpp_reader *pfile,
271+ const unsigned char *const start,
272+ size_t num_bytes)
273+{
274+ gcc_checking_assert (num_bytes > 0);
275+
276+ /* CPP_BUF_COLUMN and linemap_position_for_column both refer
277+ to offsets in bytes, but CPP_BUF_COLUMN is 0-based,
278+ whereas linemap_position_for_column is 1-based. */
279+
280+ /* Get 0-based offsets within the line. */
281+ size_t start_offset = CPP_BUF_COLUMN (pfile->buffer, start);
282+ size_t end_offset = start_offset + num_bytes - 1;
283+
284+ /* Now convert to location_t, where "columns" are 1-based byte offsets. */
285+ location_t start_loc = linemap_position_for_column (pfile->line_table,
286+ start_offset + 1);
287+ location_t end_loc = linemap_position_for_column (pfile->line_table,
288+ end_offset + 1);
289+
290+ if (start_loc == end_loc)
291+ return start_loc;
292+
293+ source_range src_range;
294+ src_range.m_start = start_loc;
295+ src_range.m_finish = end_loc;
296+ location_t combined_loc = COMBINE_LOCATION_DATA (pfile->line_table,
297+ start_loc,
298+ src_range,
299+ NULL);
300+ return combined_loc;
301+}
302+
303 /* Parse a sequence of 3 bytes starting with P and return its bidi code. */
304
305 static bidi::kind
306-get_bidi_utf8 (const unsigned char *const p)
307+get_bidi_utf8_1 (const unsigned char *const p)
308 {
309 gcc_checking_assert (p[0] == bidi::utf8_start);
310
311@@ -1340,10 +1408,25 @@ get_bidi_utf8 (const unsigned char *cons
312 return bidi::kind::NONE;
313 }
314
315+/* Parse a sequence of 3 bytes starting with P and return its bidi code.
316+ If the kind is not NONE, write the location to *OUT.*/
317+
318+static bidi::kind
319+get_bidi_utf8 (cpp_reader *pfile, const unsigned char *const p, location_t *out)
320+{
321+ bidi::kind result = get_bidi_utf8_1 (p);
322+ if (result != bidi::kind::NONE)
323+ {
324+ /* We have a sequence of 3 bytes starting at P. */
325+ *out = get_location_for_byte_range_in_cur_line (pfile, p, 3);
326+ }
327+ return result;
328+}
329+
330 /* Parse a UCN where P points just past \u or \U and return its bidi code. */
331
332 static bidi::kind
333-get_bidi_ucn (const unsigned char *p, bool is_U)
334+get_bidi_ucn_1 (const unsigned char *p, bool is_U)
335 {
336 /* 6.4.3 Universal Character Names
337 \u hex-quad
338@@ -1412,6 +1495,62 @@ get_bidi_ucn (const unsigned char *p, bo
339 return bidi::kind::NONE;
340 }
341
342+/* Parse a UCN where P points just past \u or \U and return its bidi code.
343+ If the kind is not NONE, write the location to *OUT.*/
344+
345+static bidi::kind
346+get_bidi_ucn (cpp_reader *pfile, const unsigned char *p, bool is_U,
347+ location_t *out)
348+{
349+ bidi::kind result = get_bidi_ucn_1 (p, is_U);
350+ if (result != bidi::kind::NONE)
351+ {
352+ const unsigned char *start = p - 2;
353+ size_t num_bytes = 2 + (is_U ? 8 : 4);
354+ *out = get_location_for_byte_range_in_cur_line (pfile, start, num_bytes);
355+ }
356+ return result;
357+}
358+
359+/* Subclass of rich_location for reporting on unpaired UTF-8
360+ bidirectional control character(s).
361+ Escape the source lines on output, and show all unclosed
362+ bidi context, labelling everything. */
363+
364+class unpaired_bidi_rich_location : public rich_location
365+{
366+ public:
367+ class custom_range_label : public range_label
368+ {
369+ public:
370+ label_text get_text (unsigned range_idx) const FINAL OVERRIDE
371+ {
372+ /* range 0 is the primary location; each subsequent range i + 1
373+ is for bidi::vec[i]. */
374+ if (range_idx > 0)
375+ {
376+ const bidi::context &ctxt (bidi::vec[range_idx - 1]);
377+ return label_text::borrow (bidi::to_str (ctxt.m_kind));
378+ }
379+ else
380+ return label_text::borrow (_("end of bidirectional context"));
381+ }
382+ };
383+
384+ unpaired_bidi_rich_location (cpp_reader *pfile, location_t loc)
385+ : rich_location (pfile->line_table, loc, &m_custom_label)
386+ {
387+ set_escape_on_output (true);
388+ for (unsigned i = 0; i < bidi::vec.count (); i++)
389+ add_range (bidi::vec[i].m_loc,
390+ SHOW_RANGE_WITHOUT_CARET,
391+ &m_custom_label);
392+ }
393+
394+ private:
395+ custom_range_label m_custom_label;
396+};
397+
398 /* We're closing a bidi context, that is, we've encountered a newline,
399 are closing a C-style comment, or are at the end of a string literal,
400 character constant, or identifier. Warn if this context was not
401@@ -1427,11 +1566,17 @@ maybe_warn_bidi_on_close (cpp_reader *pf
402 const location_t loc
403 = linemap_position_for_column (pfile->line_table,
404 CPP_BUF_COLUMN (pfile->buffer, p));
405- rich_location rich_loc (pfile->line_table, loc);
406- rich_loc.set_escape_on_output (true);
407- cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
408- "unpaired UTF-8 bidirectional control character "
409- "detected");
410+ unpaired_bidi_rich_location rich_loc (pfile, loc);
411+ /* cpp_callbacks doesn't yet have a way to handle singular vs plural
412+ forms of a diagnostic, so fake it for now. */
413+ if (bidi::vec.count () > 1)
414+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
415+ "unpaired UTF-8 bidirectional control characters "
416+ "detected");
417+ else
418+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
419+ "unpaired UTF-8 bidirectional control character "
420+ "detected");
421 }
422 /* We're done with this context. */
423 bidi::on_close ();
424@@ -1439,12 +1584,13 @@ maybe_warn_bidi_on_close (cpp_reader *pf
425
426 /* We're at the beginning or in the middle of an identifier/comment/string
427 literal/character constant. Warn if we've encountered a bidi character.
428- KIND says which bidi character it was; P points to it in the character
429- stream. UCN_P is true iff this bidi character was written as a UCN. */
430+ KIND says which bidi control character it was; UCN_P is true iff this bidi
431+ control character was written as a UCN. LOC is the location of the
432+ character, but is only valid if KIND != bidi::kind::NONE. */
433
434 static void
435-maybe_warn_bidi_on_char (cpp_reader *pfile, const uchar *p, bidi::kind kind,
436- bool ucn_p)
437+maybe_warn_bidi_on_char (cpp_reader *pfile, bidi::kind kind,
438+ bool ucn_p, location_t loc)
439 {
440 if (__builtin_expect (kind == bidi::kind::NONE, 1))
441 return;
442@@ -1453,9 +1599,6 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
443
444 if (warn_bidi != bidirectional_none)
445 {
446- const location_t loc
447- = linemap_position_for_column (pfile->line_table,
448- CPP_BUF_COLUMN (pfile->buffer, p));
449 rich_location rich_loc (pfile->line_table, loc);
450 rich_loc.set_escape_on_output (true);
451
452@@ -1467,9 +1610,12 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
453 {
454 if (warn_bidi == bidirectional_unpaired
455 && bidi::current_ctx_ucn_p () != ucn_p)
456- cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
457- "UTF-8 vs UCN mismatch when closing "
458- "a context by \"%s\"", bidi::to_str (kind));
459+ {
460+ rich_loc.add_range (bidi::current_ctx_loc ());
461+ cpp_warning_at (pfile, CPP_W_BIDIRECTIONAL, &rich_loc,
462+ "UTF-8 vs UCN mismatch when closing "
463+ "a context by \"%s\"", bidi::to_str (kind));
464+ }
465 }
466 else if (warn_bidi == bidirectional_any)
467 {
468@@ -1484,7 +1630,7 @@ maybe_warn_bidi_on_char (cpp_reader *pfi
469 }
470 }
471 /* We're done with this context. */
472- bidi::on_char (kind, ucn_p);
473+ bidi::on_char (kind, ucn_p, loc);
474 }
475
476 /* Skip a C-style block comment. We find the end of the comment by
477@@ -1552,8 +1698,9 @@ _cpp_skip_block_comment (cpp_reader *pfi
478 a bidirectional control character. */
479 else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
480 {
481- bidi::kind kind = get_bidi_utf8 (cur - 1);
482- maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/false);
483+ location_t loc;
484+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
485+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
486 }
487 }
488
489@@ -1586,9 +1733,9 @@ skip_line_comment (cpp_reader *pfile)
490 {
491 if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0))
492 {
493- bidi::kind kind = get_bidi_utf8 (buffer->cur);
494- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
495- /*ucn_p=*/false);
496+ location_t loc;
497+ bidi::kind kind = get_bidi_utf8 (pfile, buffer->cur, &loc);
498+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
499 }
500 buffer->cur++;
501 }
502@@ -1734,9 +1881,9 @@ forms_identifier_p (cpp_reader *pfile, i
503 if (__builtin_expect (*buffer->cur == bidi::utf8_start, 0)
504 && warn_bidi_p)
505 {
506- bidi::kind kind = get_bidi_utf8 (buffer->cur);
507- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
508- /*ucn_p=*/false);
509+ location_t loc;
510+ bidi::kind kind = get_bidi_utf8 (pfile, buffer->cur, &loc);
511+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
512 }
513 if (_cpp_valid_utf8 (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
514 state, &s))
515@@ -1748,10 +1895,12 @@ forms_identifier_p (cpp_reader *pfile, i
516 buffer->cur += 2;
517 if (warn_bidi_p)
518 {
519- bidi::kind kind = get_bidi_ucn (buffer->cur,
520- buffer->cur[-1] == 'U');
521- maybe_warn_bidi_on_char (pfile, buffer->cur, kind,
522- /*ucn_p=*/true);
523+ location_t loc;
524+ bidi::kind kind = get_bidi_ucn (pfile,
525+ buffer->cur,
526+ buffer->cur[-1] == 'U',
527+ &loc);
528+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/true, loc);
529 }
530 if (_cpp_valid_ucn (pfile, &buffer->cur, buffer->rlimit, 1 + !first,
531 state, &s, NULL, NULL))
532@@ -2327,12 +2476,15 @@ lex_raw_string (cpp_reader *pfile, cpp_t
533 }
534 else if (__builtin_expect ((unsigned char) c == bidi::utf8_start, 0)
535 && warn_bidi_p)
536- maybe_warn_bidi_on_char (pfile, pos - 1, get_bidi_utf8 (pos - 1),
537- /*ucn_p=*/false);
538+ {
539+ location_t loc;
540+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
541+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
542+ }
543 }
544
545 if (warn_bidi_p)
546- maybe_warn_bidi_on_close (pfile, pos);
547+ maybe_warn_bidi_on_close (pfile, cur);
548
549 if (CPP_OPTION (pfile, user_literals))
550 {
551@@ -2438,8 +2590,10 @@ lex_string (cpp_reader *pfile, cpp_token
552 {
553 if ((cur[0] == 'u' || cur[0] == 'U') && warn_bidi_p)
554 {
555- bidi::kind kind = get_bidi_ucn (cur + 1, cur[0] == 'U');
556- maybe_warn_bidi_on_char (pfile, cur, kind, /*ucn_p=*/true);
557+ location_t loc;
558+ bidi::kind kind = get_bidi_ucn (pfile, cur + 1, cur[0] == 'U',
559+ &loc);
560+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/true, loc);
561 }
562 cur++;
563 }
564@@ -2467,8 +2621,9 @@ lex_string (cpp_reader *pfile, cpp_token
565 saw_NUL = true;
566 else if (__builtin_expect (c == bidi::utf8_start, 0) && warn_bidi_p)
567 {
568- bidi::kind kind = get_bidi_utf8 (cur - 1);
569- maybe_warn_bidi_on_char (pfile, cur - 1, kind, /*ucn_p=*/false);
570+ location_t loc;
571+ bidi::kind kind = get_bidi_utf8 (pfile, cur - 1, &loc);
572+ maybe_warn_bidi_on_char (pfile, kind, /*ucn_p=*/false, loc);
573 }
574 }
575
diff --git a/meta/recipes-devtools/gcc/gcc/0012-gcc-Fix-argument-list-too-long-error.patch b/meta/recipes-devtools/gcc/gcc/0012-gcc-Fix-argument-list-too-long-error.patch
index 88e1715b5c..03d7a41633 100644
--- a/meta/recipes-devtools/gcc/gcc/0012-gcc-Fix-argument-list-too-long-error.patch
+++ b/meta/recipes-devtools/gcc/gcc/0012-gcc-Fix-argument-list-too-long-error.patch
@@ -30,9 +30,8 @@ diff --git a/gcc/Makefile.in b/gcc/Makefile.in
30index a67d2cc18d6..480c9366418 100644 30index a67d2cc18d6..480c9366418 100644
31--- a/gcc/Makefile.in 31--- a/gcc/Makefile.in
32+++ b/gcc/Makefile.in 32+++ b/gcc/Makefile.in
33@@ -3606,7 +3606,7 @@ install-plugin: installdirs lang.install-plugin s-header-vars install-gengtype 33 # We keep the directory structure for files in config, common/config or
34 # We keep the directory structure for files in config or c-family and .def 34 # c-family and .def files. All other files are flattened to a single directory.
35 # files. All other files are flattened to a single directory.
36 $(mkinstalldirs) $(DESTDIR)$(plugin_includedir) 35 $(mkinstalldirs) $(DESTDIR)$(plugin_includedir)
37- headers=`echo $(PLUGIN_HEADERS) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \ 36- headers=`echo $(PLUGIN_HEADERS) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \
38+ headers=`echo $(sort $(PLUGIN_HEADERS)) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \ 37+ headers=`echo $(sort $(PLUGIN_HEADERS)) $$(cd $(srcdir); echo *.h *.def) | tr ' ' '\012' | sort -u`; \
diff --git a/meta/recipes-devtools/gcc/gcc/0033-Re-introduce-spe-commandline-options.patch b/meta/recipes-devtools/gcc/gcc/0033-Re-introduce-spe-commandline-options.patch
index ba7c2b8fd5..43d881fa5e 100644
--- a/meta/recipes-devtools/gcc/gcc/0033-Re-introduce-spe-commandline-options.patch
+++ b/meta/recipes-devtools/gcc/gcc/0033-Re-introduce-spe-commandline-options.patch
@@ -33,6 +33,6 @@ index f95b8279270..0e52d51409d 100644
33+Target RejectNegative Var(rs6000_spe_abi, 0) 33+Target RejectNegative Var(rs6000_spe_abi, 0)
34+Do not use the SPE ABI extensions. 34+Do not use the SPE ABI extensions.
35+ 35+
36 ; Altivec ABI
36 mabi=altivec 37 mabi=altivec
37 Target RejectNegative Var(rs6000_altivec_abi) Save 38 Target RejectNegative Var(rs6000_altivec_abi) Save
38 Use the AltiVec ABI extensions.
diff --git a/meta/recipes-devtools/gcc/gcc/0036-mingw32-Enable-operation_not_supported.patch b/meta/recipes-devtools/gcc/gcc/0036-mingw32-Enable-operation_not_supported.patch
index de82a3a539..4db3d15554 100644
--- a/meta/recipes-devtools/gcc/gcc/0036-mingw32-Enable-operation_not_supported.patch
+++ b/meta/recipes-devtools/gcc/gcc/0036-mingw32-Enable-operation_not_supported.patch
@@ -16,11 +16,11 @@ index 68ac72a78fb..71cd5815b81 100644
16--- a/libstdc++-v3/config/os/mingw32/error_constants.h 16--- a/libstdc++-v3/config/os/mingw32/error_constants.h
17+++ b/libstdc++-v3/config/os/mingw32/error_constants.h 17+++ b/libstdc++-v3/config/os/mingw32/error_constants.h
18@@ -107,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 18@@ -107,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
19 #ifdef _GLIBCXX_HAVE_EPERM 19 #ifdef EPERM
20 operation_not_permitted = EPERM, 20 operation_not_permitted = EPERM,
21 #endif 21 #endif
22-// operation_not_supported = EOPNOTSUPP, 22-// operation_not_supported = EOPNOTSUPP,
23+ operation_not_supported = EOPNOTSUPP, 23+ operation_not_supported = EOPNOTSUPP,
24 #ifdef _GLIBCXX_HAVE_EWOULDBLOCK 24 #ifdef EWOULDBLOCK
25 operation_would_block = EWOULDBLOCK, 25 operation_would_block = EWOULDBLOCK,
26 #endif 26 #endif
diff --git a/meta/recipes-devtools/gcc/gcc_10.2.bb b/meta/recipes-devtools/gcc/gcc_10.3.bb
index 7d93590588..7d93590588 100644
--- a/meta/recipes-devtools/gcc/gcc_10.2.bb
+++ b/meta/recipes-devtools/gcc/gcc_10.3.bb
diff --git a/meta/recipes-devtools/gcc/libgcc-initial_10.2.bb b/meta/recipes-devtools/gcc/libgcc-initial_10.3.bb
index 0c698c26ec..0c698c26ec 100644
--- a/meta/recipes-devtools/gcc/libgcc-initial_10.2.bb
+++ b/meta/recipes-devtools/gcc/libgcc-initial_10.3.bb
diff --git a/meta/recipes-devtools/gcc/libgcc_10.2.bb b/meta/recipes-devtools/gcc/libgcc_10.3.bb
index ea210a1130..ea210a1130 100644
--- a/meta/recipes-devtools/gcc/libgcc_10.2.bb
+++ b/meta/recipes-devtools/gcc/libgcc_10.3.bb
diff --git a/meta/recipes-devtools/gcc/libgfortran_10.2.bb b/meta/recipes-devtools/gcc/libgfortran_10.3.bb
index 71dd8b4bdc..71dd8b4bdc 100644
--- a/meta/recipes-devtools/gcc/libgfortran_10.2.bb
+++ b/meta/recipes-devtools/gcc/libgfortran_10.3.bb
diff --git a/meta/recipes-devtools/gnu-config/gnu-config_git.bb b/meta/recipes-devtools/gnu-config/gnu-config_git.bb
index ecbd60e72a..da52c943f5 100644
--- a/meta/recipes-devtools/gnu-config/gnu-config_git.bb
+++ b/meta/recipes-devtools/gnu-config/gnu-config_git.bb
@@ -12,7 +12,7 @@ INHIBIT_DEFAULT_DEPS = "1"
12SRCREV = "6faca61810d335c7837f320733fe8e15a1431fc2" 12SRCREV = "6faca61810d335c7837f320733fe8e15a1431fc2"
13PV = "20210125+git${SRCPV}" 13PV = "20210125+git${SRCPV}"
14 14
15SRC_URI = "git://git.savannah.gnu.org/config.git;branch=master \ 15SRC_URI = "git://git.savannah.gnu.org/git/config.git;protocol=https;branch=master \
16 file://gnu-configize.in" 16 file://gnu-configize.in"
17S = "${WORKDIR}/git" 17S = "${WORKDIR}/git"
18UPSTREAM_CHECK_COMMITS = "1" 18UPSTREAM_CHECK_COMMITS = "1"
diff --git a/meta/recipes-devtools/go/go-1.16.8.inc b/meta/recipes-devtools/go/go-1.16.15.inc
index acc2300a28..8b1ad22bcc 100644
--- a/meta/recipes-devtools/go/go-1.16.8.inc
+++ b/meta/recipes-devtools/go/go-1.16.15.inc
@@ -1,8 +1,8 @@
1require go-common.inc 1require go-common.inc
2 2
3GO_BASEVERSION = "1.16" 3GO_BASEVERSION = "1.16"
4PV = "1.16.8" 4PV = "1.16.15"
5FILESEXTRAPATHS_prepend := "${FILE_DIRNAME}/go-${GO_BASEVERSION}:" 5FILESEXTRAPATHS:prepend := "${FILE_DIRNAME}/go-${GO_BASEVERSION}:"
6 6
7LIC_FILES_CHKSUM = "file://LICENSE;md5=5d4950ecb7b26d2c5e4e7b4e0dd74707" 7LIC_FILES_CHKSUM = "file://LICENSE;md5=5d4950ecb7b26d2c5e4e7b4e0dd74707"
8 8
@@ -18,7 +18,7 @@ SRC_URI += "\
18 file://0009-Revert-cmd-go-make-sure-CC-and-CXX-are-absolute.patch \ 18 file://0009-Revert-cmd-go-make-sure-CC-and-CXX-are-absolute.patch \
19 file://0001-encoding-xml-handle-leading-trailing-or-double-colon.patch \ 19 file://0001-encoding-xml-handle-leading-trailing-or-double-colon.patch \
20" 20"
21SRC_URI[main.sha256sum] = "8f2a8c24b793375b3243df82fdb0c8387486dcc8a892ca1c991aa99ace086b98" 21SRC_URI[main.sha256sum] = "90a08c689279e35f3865ba510998c33a63255c36089b3ec206c912fc0568c3d3"
22 22
23# Upstream don't believe it is a signifiant real world issue and will only 23# Upstream don't believe it is a signifiant real world issue and will only
24# fix in 1.17 onwards where we can drop this. 24# fix in 1.17 onwards where we can drop this.
diff --git a/meta/recipes-devtools/go/go-binary-native_1.16.8.bb b/meta/recipes-devtools/go/go-binary-native_1.16.15.bb
index 926222089d..ba11ee5695 100644
--- a/meta/recipes-devtools/go/go-binary-native_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-binary-native_1.16.15.bb
@@ -8,8 +8,8 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=5d4950ecb7b26d2c5e4e7b4e0dd74707"
8PROVIDES = "go-native" 8PROVIDES = "go-native"
9 9
10SRC_URI = "https://dl.google.com/go/go${PV}.${BUILD_GOOS}-${BUILD_GOARCH}.tar.gz;name=go_${BUILD_GOTUPLE}" 10SRC_URI = "https://dl.google.com/go/go${PV}.${BUILD_GOOS}-${BUILD_GOARCH}.tar.gz;name=go_${BUILD_GOTUPLE}"
11SRC_URI[go_linux_amd64.sha256sum] = "f32501aeb8b7b723bc7215f6c373abb6981bbc7e1c7b44e9f07317e1a300dce2" 11SRC_URI[go_linux_amd64.sha256sum] = "77c782a633186d78c384f972fb113a43c24be0234c42fef22c2d8c4c4c8e7475"
12SRC_URI[go_linux_arm64.sha256sum] = "430dbe185417204f6788913197ab3b189b6deae9c9b524f262858e53dab239c2" 12SRC_URI[go_linux_arm64.sha256sum] = "c2f27f0ce5620a9bc2ff3446165d1974ef94e9b885ec12dbfa3c07e0e198b7ce"
13 13
14UPSTREAM_CHECK_URI = "https://golang.org/dl/" 14UPSTREAM_CHECK_URI = "https://golang.org/dl/"
15UPSTREAM_CHECK_REGEX = "go(?P<pver>\d+(\.\d+)+)\.linux" 15UPSTREAM_CHECK_REGEX = "go(?P<pver>\d+(\.\d+)+)\.linux"
diff --git a/meta/recipes-devtools/go/go-cross-canadian_1.16.8.bb b/meta/recipes-devtools/go/go-cross-canadian_1.16.15.bb
index 7ac9449e47..7ac9449e47 100644
--- a/meta/recipes-devtools/go/go-cross-canadian_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-cross-canadian_1.16.15.bb
diff --git a/meta/recipes-devtools/go/go-cross_1.16.8.bb b/meta/recipes-devtools/go/go-cross_1.16.15.bb
index 80b5a03f6c..80b5a03f6c 100644
--- a/meta/recipes-devtools/go/go-cross_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-cross_1.16.15.bb
diff --git a/meta/recipes-devtools/go/go-crosssdk_1.16.8.bb b/meta/recipes-devtools/go/go-crosssdk_1.16.15.bb
index 1857c8a577..1857c8a577 100644
--- a/meta/recipes-devtools/go/go-crosssdk_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-crosssdk_1.16.15.bb
diff --git a/meta/recipes-devtools/go/go-native_1.16.8.bb b/meta/recipes-devtools/go/go-native_1.16.15.bb
index f14892cdb0..f14892cdb0 100644
--- a/meta/recipes-devtools/go/go-native_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-native_1.16.15.bb
diff --git a/meta/recipes-devtools/go/go-runtime_1.16.8.bb b/meta/recipes-devtools/go/go-runtime_1.16.15.bb
index 63464a1501..63464a1501 100644
--- a/meta/recipes-devtools/go/go-runtime_1.16.8.bb
+++ b/meta/recipes-devtools/go/go-runtime_1.16.15.bb
diff --git a/meta/recipes-devtools/go/go_1.16.8.bb b/meta/recipes-devtools/go/go_1.16.15.bb
index 4e9e0ebec8..4e9e0ebec8 100644
--- a/meta/recipes-devtools/go/go_1.16.8.bb
+++ b/meta/recipes-devtools/go/go_1.16.15.bb
diff --git a/meta/recipes-devtools/patchelf/patchelf/0001-merge-from-PR243.patch b/meta/recipes-devtools/patchelf/patchelf/0001-merge-from-PR243.patch
new file mode 100644
index 0000000000..a5322f0375
--- /dev/null
+++ b/meta/recipes-devtools/patchelf/patchelf/0001-merge-from-PR243.patch
@@ -0,0 +1,47 @@
1From 6ac5c1350834b9da81ab90ab5ba4e5bf507c6c0d Mon Sep 17 00:00:00 2001
2From: Satadru Pramanik <satadru@gmail.com>
3Date: Thu, 20 May 2021 16:52:21 -0400
4Subject: [PATCH] merge from PR243
5
6Upstream-Status: Backport
7
8Reference to upstream patch:
9https://github.com/NixOS/patchelf/commit/4efbce410d00c8cb43f134181d07b364bcf78022
10
11[OP: tweak patch to apply to patchelf v0.10]
12Signed-off-by: Ovidiu Panait <ovidiu.panait@windriver.com>
13[OP: tweak patch to apply to patchelf v0.12]
14Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
15---
16 src/patchelf.cc | 5 ++++-
17 1 file changed, 4 insertions(+), 1 deletion(-)
18
19diff --git a/src/patchelf.cc b/src/patchelf.cc
20index 1854cfa..73a3a86 100644
21--- a/src/patchelf.cc
22+++ b/src/patchelf.cc
23@@ -774,12 +774,15 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
24 PT_LOAD segment located directly after the last virtual address
25 page of other segments. */
26 Elf_Addr startPage = 0;
27+ Elf_Addr firstPage = 0;
28 for (unsigned int i = 0; i < phdrs.size(); ++i) {
29 Elf_Addr thisPage = roundUp(rdi(phdrs[i].p_vaddr) + rdi(phdrs[i].p_memsz), getPageSize());
30 if (thisPage > startPage) startPage = thisPage;
31+ if (rdi(phdrs[i].p_type) == PT_PHDR) firstPage = rdi(phdrs[i].p_vaddr) - rdi(phdrs[i].p_offset);
32 }
33
34 debug("last page is 0x%llx\n", (unsigned long long) startPage);
35+ debug("first page is 0x%llx\n", (unsigned long long) firstPage);
36
37 /* When normalizing note segments we will in the worst case be adding
38 1 program header for each SHT_NOTE section. */
39@@ -852,7 +855,7 @@ void ElfFile<ElfFileParamNames>::rewriteSectionsLibrary()
40 assert(curOff == startOffset + neededSpace);
41
42 /* Write out the updated program and section headers */
43- rewriteHeaders(hdr->e_phoff);
44+ rewriteHeaders(firstPage + hdr->e_phoff);
45 }
46
47
diff --git a/meta/recipes-devtools/patchelf/patchelf_0.12.bb b/meta/recipes-devtools/patchelf/patchelf_0.12.bb
index 390a8110da..007435a719 100644
--- a/meta/recipes-devtools/patchelf/patchelf_0.12.bb
+++ b/meta/recipes-devtools/patchelf/patchelf_0.12.bb
@@ -8,6 +8,7 @@ SRC_URI = "git://github.com/NixOS/patchelf;protocol=https;branch=master \
8 file://handle-read-only-files.patch \ 8 file://handle-read-only-files.patch \
9 file://6edec83653ce1b5fc201ff6db93b966394766814.patch \ 9 file://6edec83653ce1b5fc201ff6db93b966394766814.patch \
10 file://alignmentfix.patch \ 10 file://alignmentfix.patch \
11 file://0001-merge-from-PR243.patch \
11 " 12 "
12SRCREV = "8d3a16e97294e3c5521c61b4c8835499c9918264" 13SRCREV = "8d3a16e97294e3c5521c61b4c8835499c9918264"
13 14
diff --git a/meta/recipes-devtools/python-numpy/files/CVE-2021-41496.patch b/meta/recipes-devtools/python-numpy/files/CVE-2021-41496.patch
new file mode 100644
index 0000000000..0afc79ae0d
--- /dev/null
+++ b/meta/recipes-devtools/python-numpy/files/CVE-2021-41496.patch
@@ -0,0 +1,64 @@
1From 86d81322c5c0ab67f89d64f56f6e77d4fe185910 Mon Sep 17 00:00:00 2001
2From: Warren Weckesser <warren.weckesser@gmail.com>
3Date: Tue, 29 Mar 2022 15:58:00 +0800
4Subject: [PATCH] BUG: f2py: Simplify creation of an exception message. Closes
5 gh-19000.
6
7CVE: CVE-2021-41496
8
9Upstream-Status: Backport [https://github.com/numpy/numpy/commit/271010f1037150e95017f803f4214b8861e528f2]
10
11Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
12---
13 numpy/f2py/src/fortranobject.c | 26 ++++++++++++--------------
14 1 file changed, 12 insertions(+), 14 deletions(-)
15
16diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c
17index 3275f90..85c9c7f 100644
18--- a/numpy/f2py/src/fortranobject.c
19+++ b/numpy/f2py/src/fortranobject.c
20@@ -637,14 +637,14 @@ static int check_and_fix_dimensions(const PyArrayObject* arr,
21 npy_intp *dims);
22
23 static int
24-count_negative_dimensions(const int rank,
25+find_first_negative_dimension(const int rank,
26 const npy_intp *dims) {
27- int i=0,r=0;
28- while (i<rank) {
29- if (dims[i] < 0) ++r;
30- ++i;
31+ for (int i = 0; i < rank; ++i) {
32+ if (dims[i] < 0) {
33+ return i;
34+ }
35 }
36- return r;
37+ return -1;
38 }
39
40 #ifdef DEBUG_COPY_ND_ARRAY
41@@ -721,14 +721,12 @@ PyArrayObject* array_from_pyobj(const int type_num,
42 || ((intent & F2PY_OPTIONAL) && (obj==Py_None))
43 ) {
44 /* intent(cache), optional, intent(hide) */
45- if (count_negative_dimensions(rank,dims) > 0) {
46- int i;
47- strcpy(mess, "failed to create intent(cache|hide)|optional array"
48- "-- must have defined dimensions but got (");
49- for(i=0;i<rank;++i)
50- sprintf(mess+strlen(mess),"%" NPY_INTP_FMT ",",dims[i]);
51- strcat(mess, ")");
52- PyErr_SetString(PyExc_ValueError,mess);
53+ int i = find_first_negative_dimension(rank, dims);
54+ if (i >= 0) {
55+ PyErr_Format(PyExc_ValueError,
56+ "failed to create intent(cache|hide)|optional array"
57+ " -- must have defined dimensions, but dims[%d] = %"
58+ NPY_INTP_FMT, i, dims[i]);
59 return NULL;
60 }
61 arr = (PyArrayObject *)
62--
632.25.1
64
diff --git a/meta/recipes-devtools/python-numpy/python3-numpy_1.20.1.bb b/meta/recipes-devtools/python-numpy/python3-numpy_1.20.1.bb
index 6c3b886782..9e55e74d2c 100644
--- a/meta/recipes-devtools/python-numpy/python3-numpy_1.20.1.bb
+++ b/meta/recipes-devtools/python-numpy/python3-numpy_1.20.1.bb
@@ -10,6 +10,7 @@ SRCNAME = "numpy"
10SRC_URI = "https://github.com/${SRCNAME}/${SRCNAME}/releases/download/v${PV}/${SRCNAME}-${PV}.tar.gz \ 10SRC_URI = "https://github.com/${SRCNAME}/${SRCNAME}/releases/download/v${PV}/${SRCNAME}-${PV}.tar.gz \
11 file://0001-Don-t-search-usr-and-so-on-for-libraries-by-default-.patch \ 11 file://0001-Don-t-search-usr-and-so-on-for-libraries-by-default-.patch \
12 file://0001-numpy-core-Define-RISCV-32-support.patch \ 12 file://0001-numpy-core-Define-RISCV-32-support.patch \
13 file://CVE-2021-41496.patch \
13 file://run-ptest \ 14 file://run-ptest \
14" 15"
15SRC_URI[sha256sum] = "9bf51d69ebb4ca9239e55bedc2185fe2c0ec222da0adee7ece4125414676846d" 16SRC_URI[sha256sum] = "9bf51d69ebb4ca9239e55bedc2185fe2c0ec222da0adee7ece4125414676846d"
diff --git a/meta/recipes-devtools/python/python3-pyelftools_0.27.bb b/meta/recipes-devtools/python/python3-pyelftools_0.27.bb
index 0cfd99504b..f8b9d420a5 100644
--- a/meta/recipes-devtools/python/python3-pyelftools_0.27.bb
+++ b/meta/recipes-devtools/python/python3-pyelftools_0.27.bb
@@ -11,3 +11,5 @@ PYPI_PACKAGE = "pyelftools"
11inherit pypi setuptools3 11inherit pypi setuptools3
12 12
13BBCLASSEXTEND = "native" 13BBCLASSEXTEND = "native"
14
15RDEPENDS_${PN} += "${PYTHON_PN}-debugger ${PYTHON_PN}-pprint"
diff --git a/meta/recipes-devtools/python/python3/0001-Makefile-fix-Issue36464-parallel-build-race-problem.patch b/meta/recipes-devtools/python/python3/0001-Makefile-fix-Issue36464-parallel-build-race-problem.patch
deleted file mode 100644
index 237645bc60..0000000000
--- a/meta/recipes-devtools/python/python3/0001-Makefile-fix-Issue36464-parallel-build-race-problem.patch
+++ /dev/null
@@ -1,34 +0,0 @@
1From 840fda32c82550259d02a7a56a78a9c05162b1a1 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Wed, 8 May 2019 16:10:29 +0800
4Subject: [PATCH] Makefile: fix Issue36464 (parallel build race problem)
5
6When using make -j with the 'install' target, it's possible for altbininstall
7(which normally creates BINDIR) and libainstall (which doesn't, though it
8installs python-config there) to race, resulting in a failure due to
9attempting to install python-config into a nonexistent BINDIR. Ensure it also
10exists in the libainstall target.
11
12Upstream-Status: Submitted [https://github.com/python/cpython/pull/13186]
13
14Signed-off-by: Changqing Li <changqing.li@windriver.com>
15---
16 Makefile.pre.in | 2 +-
17 1 file changed, 1 insertion(+), 1 deletion(-)
18
19diff --git a/Makefile.pre.in b/Makefile.pre.in
20index 15f3687..7e9f173 100644
21--- a/Makefile.pre.in
22+++ b/Makefile.pre.in
23@@ -1456,7 +1456,7 @@ LIBPL= @LIBPL@
24 LIBPC= $(LIBDIR)/pkgconfig
25
26 libainstall: @DEF_MAKE_RULE@ python-config
27- @for i in $(LIBDIR) $(LIBPL) $(LIBPC); \
28+ @for i in $(LIBDIR) $(LIBPL) $(LIBPC) $(BINDIR); \
29 do \
30 if test ! -d $(DESTDIR)$$i; then \
31 echo "Creating directory $$i"; \
32--
332.7.4
34
diff --git a/meta/recipes-devtools/python/python3/0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch b/meta/recipes-devtools/python/python3/0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch
index c4fae09a5b..99968b81de 100644
--- a/meta/recipes-devtools/python/python3/0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch
+++ b/meta/recipes-devtools/python/python3/0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch
@@ -1,7 +1,8 @@
1From 1ad771d86728ee2ed30e202e9768d8d825f96467 Mon Sep 17 00:00:00 2001 1From d9eb634b3d2e6ba831e864c50f6a37c48edfc4f3 Mon Sep 17 00:00:00 2001
2From: Matthias Schoepfer <matthias.schoepfer@ithinx.io> 2From: Matthias Schoepfer <matthias.schoepfer@ithinx.io>
3Date: Fri, 31 May 2019 15:34:34 +0200 3Date: Fri, 31 May 2019 15:34:34 +0200
4Subject: [PATCH] bpo-36852: proper detection of mips architecture for soft 4Subject: [PATCH] bpo-36852: proper detection of mips architecture for soft
5
5 float 6 float
6 7
7When (cross) compiling for softfloat mips, __mips_hard_float will not be 8When (cross) compiling for softfloat mips, __mips_hard_float will not be
@@ -13,18 +14,18 @@ to do this in a more autoconf/autotools manner.
13Upstream-Status: Submitted [https://github.com/python/cpython/pull/13196] 14Upstream-Status: Submitted [https://github.com/python/cpython/pull/13196]
14Signed-off-by: Matthias Schoepfer <matthias.schoepfer@ithinx.io> 15Signed-off-by: Matthias Schoepfer <matthias.schoepfer@ithinx.io>
15 16
16%% original patch: 0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch 17
17--- 18---
18 configure.ac | 175 +++++++-------------------------------------------- 19 configure.ac | 175 +++++++--------------------------------------------
19 1 file changed, 21 insertions(+), 154 deletions(-) 20 1 file changed, 21 insertions(+), 154 deletions(-)
20 21
21diff --git a/configure.ac b/configure.ac 22diff --git a/configure.ac b/configure.ac
22index ede710e..bc81b0b 100644 23index e2979a8..337182d 100644
23--- a/configure.ac 24--- a/configure.ac
24+++ b/configure.ac 25+++ b/configure.ac
25@@ -710,160 +710,27 @@ fi 26@@ -728,160 +728,27 @@ then
26 MULTIARCH=$($CC --print-multiarch 2>/dev/null) 27 fi
27 AC_SUBST(MULTIARCH) 28
28 29
29-AC_MSG_CHECKING([for the platform triplet based on compiler characteristics]) 30-AC_MSG_CHECKING([for the platform triplet based on compiler characteristics])
30-cat >> conftest.c <<EOF 31-cat >> conftest.c <<EOF
@@ -202,8 +203,5 @@ index ede710e..bc81b0b 100644
202+ ;; 203+ ;;
203+esac 204+esac
204 205
205 if test x$PLATFORM_TRIPLET != x && test x$MULTIARCH != x; then 206 if test x$PLATFORM_TRIPLET != xdarwin; then
206 if test x$PLATFORM_TRIPLET != x$MULTIARCH; then 207 MULTIARCH=$($CC --print-multiarch 2>/dev/null)
207--
2082.24.1
209
diff --git a/meta/recipes-devtools/python/python3_3.9.5.bb b/meta/recipes-devtools/python/python3_3.9.9.bb
index 2b05bd530e..f41529833c 100644
--- a/meta/recipes-devtools/python/python3_3.9.5.bb
+++ b/meta/recipes-devtools/python/python3_3.9.9.bb
@@ -20,7 +20,6 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \
20 file://python-config.patch \ 20 file://python-config.patch \
21 file://0001-Makefile.pre-use-qemu-wrapper-when-gathering-profile.patch \ 21 file://0001-Makefile.pre-use-qemu-wrapper-when-gathering-profile.patch \
22 file://0001-python3-use-cc_basename-to-replace-CC-for-checking-c.patch \ 22 file://0001-python3-use-cc_basename-to-replace-CC-for-checking-c.patch \
23 file://0001-Makefile-fix-Issue36464-parallel-build-race-problem.patch \
24 file://0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch \ 23 file://0001-bpo-36852-proper-detection-of-mips-architecture-for-.patch \
25 file://crosspythonpath.patch \ 24 file://crosspythonpath.patch \
26 file://0001-Use-FLAG_REF-always-for-interned-strings.patch \ 25 file://0001-Use-FLAG_REF-always-for-interned-strings.patch \
@@ -39,7 +38,7 @@ SRC_URI_append_class-native = " \
39 file://12-distutils-prefix-is-inside-staging-area.patch \ 38 file://12-distutils-prefix-is-inside-staging-area.patch \
40 file://0001-Don-t-search-system-for-headers-libraries.patch \ 39 file://0001-Don-t-search-system-for-headers-libraries.patch \
41 " 40 "
42SRC_URI[sha256sum] = "0c5a140665436ec3dbfbb79e2dfb6d192655f26ef4a29aeffcb6d1820d716d83" 41SRC_URI[sha256sum] = "06828c04a573c073a4e51c4292a27c1be4ae26621c3edc7cf9318418ce3b6d27"
43 42
44# exclude pre-releases for both python 2.x and 3.x 43# exclude pre-releases for both python 2.x and 3.x
45UPSTREAM_CHECK_REGEX = "[Pp]ython-(?P<pver>\d+(\.\d+)+).tar" 44UPSTREAM_CHECK_REGEX = "[Pp]ython-(?P<pver>\d+(\.\d+)+).tar"
diff --git a/meta/recipes-devtools/qemu/qemu.inc b/meta/recipes-devtools/qemu/qemu.inc
index 463339e42b..568ef1be94 100644
--- a/meta/recipes-devtools/qemu/qemu.inc
+++ b/meta/recipes-devtools/qemu/qemu.inc
@@ -70,6 +70,11 @@ SRC_URI = "https://download.qemu.org/${BPN}-${PV}.tar.xz \
70 file://CVE-2021-3607.patch \ 70 file://CVE-2021-3607.patch \
71 file://CVE-2021-3608.patch \ 71 file://CVE-2021-3608.patch \
72 file://CVE-2021-3682.patch \ 72 file://CVE-2021-3682.patch \
73 file://CVE-2021-3713.patch \
74 file://CVE-2021-3748.patch \
75 file://CVE-2021-3930.patch \
76 file://CVE-2021-20196_1.patch \
77 file://CVE-2021-20196_2.patch \
73 " 78 "
74UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar" 79UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+(\.\d+)+)\.tar"
75 80
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_1.patch b/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_1.patch
new file mode 100644
index 0000000000..8b1ad0423b
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_1.patch
@@ -0,0 +1,54 @@
1From e907ff3d4cb7fd20d402f45355059e67d0dc93e7 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
3Date: Wed, 24 Nov 2021 17:15:34 +0100
4Subject: [PATCH 11/12] hw/block/fdc: Extract blk_create_empty_drive()
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9We are going to re-use this code in the next commit,
10so extract it as a new blk_create_empty_drive() function.
11
12Inspired-by: Hanna Reitz <hreitz@redhat.com>
13Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14Message-id: 20211124161536.631563-2-philmd@redhat.com
15Signed-off-by: John Snow <jsnow@redhat.com>
16
17Upstream-Status: Backport [b154791e7b6d4ca5cdcd54443484d97360bd7ad2]
18CVE: CVE-2021-20196
19
20Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
21---
22 hw/block/fdc.c | 9 +++++++--
23 1 file changed, 7 insertions(+), 2 deletions(-)
24
25diff --git a/hw/block/fdc.c b/hw/block/fdc.c
26index 4c2c35e22..854b4f172 100644
27--- a/hw/block/fdc.c
28+++ b/hw/block/fdc.c
29@@ -61,6 +61,12 @@
30 } while (0)
31
32
33+/* Anonymous BlockBackend for empty drive */
34+static BlockBackend *blk_create_empty_drive(void)
35+{
36+ return blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
37+}
38+
39 /********************************************************/
40 /* qdev floppy bus */
41
42@@ -543,8 +549,7 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
43 }
44
45 if (!dev->conf.blk) {
46- /* Anonymous BlockBackend for an empty drive */
47- dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
48+ dev->conf.blk = blk_create_empty_drive();
49 ret = blk_attach_dev(dev->conf.blk, qdev);
50 assert(ret == 0);
51
52--
532.31.1
54
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_2.patch b/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_2.patch
new file mode 100644
index 0000000000..dd442ccb8f
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2021-20196_2.patch
@@ -0,0 +1,67 @@
1From 1d48445a951fd5504190a38abeda70ea9372cf77 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= <philmd@redhat.com>
3Date: Wed, 24 Nov 2021 17:15:35 +0100
4Subject: [PATCH 12/12] hw/block/fdc: Kludge missing floppy drive to fix
5 CVE-2021-20196
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Guest might select another drive on the bus by setting the
11DRIVE_SEL bit of the DIGITAL OUTPUT REGISTER (DOR).
12The current controller model doesn't expect a BlockBackend
13to be NULL. A simple way to fix CVE-2021-20196 is to create
14an empty BlockBackend when it is missing. All further
15accesses will be safely handled, and the controller state
16machines keep behaving correctly.
17
18Cc: qemu-stable@nongnu.org
19Fixes: CVE-2021-20196
20Reported-by: Gaoning Pan (Ant Security Light-Year Lab) <pgn@zju.edu.cn>
21Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
22Reviewed-by: Hanna Reitz <hreitz@redhat.com>
23Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
24Message-id: 20211124161536.631563-3-philmd@redhat.com
25BugLink: https://bugs.launchpad.net/qemu/+bug/1912780
26Resolves: https://gitlab.com/qemu-project/qemu/-/issues/338
27Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
28Reviewed-by: Hanna Reitz <hreitz@redhat.com>
29Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
30Signed-off-by: John Snow <jsnow@redhat.com>
31
32Upstream-Status: Backport [1ab95af033a419e7a64e2d58e67dd96b20af5233]
33CVE: CVE-2021-20196
34
35Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
36---
37 hw/block/fdc.c | 14 +++++++++++++-
38 1 file changed, 13 insertions(+), 1 deletion(-)
39
40diff --git a/hw/block/fdc.c b/hw/block/fdc.c
41index 854b4f172..a736c4d14 100644
42--- a/hw/block/fdc.c
43+++ b/hw/block/fdc.c
44@@ -1365,7 +1365,19 @@ static FDrive *get_drv(FDCtrl *fdctrl, int unit)
45
46 static FDrive *get_cur_drv(FDCtrl *fdctrl)
47 {
48- return get_drv(fdctrl, fdctrl->cur_drv);
49+ FDrive *cur_drv = get_drv(fdctrl, fdctrl->cur_drv);
50+
51+ if (!cur_drv->blk) {
52+ /*
53+ * Kludge: empty drive line selected. Create an anonymous
54+ * BlockBackend to avoid NULL deref with various BlockBackend
55+ * API calls within this model (CVE-2021-20196).
56+ * Due to the controller QOM model limitations, we don't
57+ * attach the created to the controller device.
58+ */
59+ cur_drv->blk = blk_create_empty_drive();
60+ }
61+ return cur_drv;
62 }
63
64 /* Status A register : 0x00 (read-only) */
65--
662.31.1
67
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2021-3713.patch b/meta/recipes-devtools/qemu/qemu/CVE-2021-3713.patch
new file mode 100644
index 0000000000..33fca66d3d
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2021-3713.patch
@@ -0,0 +1,68 @@
1From 9a8f71ec660e67c51cc5905dd9d2a12ff78ce743 Mon Sep 17 00:00:00 2001
2From: Gerd Hoffmann <kraxel@redhat.com>
3Date: Wed, 18 Aug 2021 14:05:05 +0200
4Subject: [PATCH 08/12] uas: add stream number sanity checks.
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9The device uses the guest-supplied stream number unchecked, which can
10lead to guest-triggered out-of-band access to the UASDevice->data3 and
11UASDevice->status3 fields. Add the missing checks.
12
13Fixes: CVE-2021-3713
14Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
15Reported-by: Chen Zhe <chenzhe@huawei.com>
16Reported-by: Tan Jingguo <tanjingguo@huawei.com>
17Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18Message-Id: <20210818120505.1258262-2-kraxel@redhat.com>
19(cherry picked from commit 13b250b12ad3c59114a6a17d59caf073ce45b33a)
20Signed-off-by: Michael Roth <michael.roth@amd.com>
21
22Upstream-Status: Backport [36403e8788a264dc96174f52584681ebcb4f54b1]
23CVE: CVE-2021-3713
24
25Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
26---
27 hw/usb/dev-uas.c | 11 +++++++++++
28 1 file changed, 11 insertions(+)
29
30diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
31index cec071d96..157734eb0 100644
32--- a/hw/usb/dev-uas.c
33+++ b/hw/usb/dev-uas.c
34@@ -831,6 +831,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
35 }
36 break;
37 case UAS_PIPE_ID_STATUS:
38+ if (p->stream > UAS_MAX_STREAMS) {
39+ goto err_stream;
40+ }
41 if (p->stream) {
42 QTAILQ_FOREACH(st, &uas->results, next) {
43 if (st->stream == p->stream) {
44@@ -858,6 +861,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
45 break;
46 case UAS_PIPE_ID_DATA_IN:
47 case UAS_PIPE_ID_DATA_OUT:
48+ if (p->stream > UAS_MAX_STREAMS) {
49+ goto err_stream;
50+ }
51 if (p->stream) {
52 req = usb_uas_find_request(uas, p->stream);
53 } else {
54@@ -893,6 +899,11 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
55 p->status = USB_RET_STALL;
56 break;
57 }
58+
59+err_stream:
60+ error_report("%s: invalid stream %d", __func__, p->stream);
61+ p->status = USB_RET_STALL;
62+ return;
63 }
64
65 static void usb_uas_unrealize(USBDevice *dev)
66--
672.31.1
68
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2021-3748.patch b/meta/recipes-devtools/qemu/qemu/CVE-2021-3748.patch
new file mode 100644
index 0000000000..4765f24739
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2021-3748.patch
@@ -0,0 +1,127 @@
1From bacc200f623647632258f7efc0f098ac30dd4225 Mon Sep 17 00:00:00 2001
2From: Jason Wang <jasowang@redhat.com>
3Date: Thu, 2 Sep 2021 13:44:12 +0800
4Subject: [PATCH 09/12] virtio-net: fix use after unmap/free for sg
5
6When mergeable buffer is enabled, we try to set the num_buffers after
7the virtqueue elem has been unmapped. This will lead several issues,
8E.g a use after free when the descriptor has an address which belongs
9to the non direct access region. In this case we use bounce buffer
10that is allocated during address_space_map() and freed during
11address_space_unmap().
12
13Fixing this by storing the elems temporarily in an array and delay the
14unmap after we set the the num_buffers.
15
16This addresses CVE-2021-3748.
17
18Reported-by: Alexander Bulekov <alxndr@bu.edu>
19Fixes: fbe78f4f55c6 ("virtio-net support")
20Cc: qemu-stable@nongnu.org
21Signed-off-by: Jason Wang <jasowang@redhat.com>
22
23Upstream-Status: Backport [bedd7e93d01961fcb16a97ae45d93acf357e11f6]
24CVE: CVE-2021-3748
25
26Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
27---
28 hw/net/virtio-net.c | 39 ++++++++++++++++++++++++++++++++-------
29 1 file changed, 32 insertions(+), 7 deletions(-)
30
31diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
32index 9179013ac..df1d30e2c 100644
33--- a/hw/net/virtio-net.c
34+++ b/hw/net/virtio-net.c
35@@ -1665,10 +1665,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
36 VirtIONet *n = qemu_get_nic_opaque(nc);
37 VirtIONetQueue *q = virtio_net_get_subqueue(nc);
38 VirtIODevice *vdev = VIRTIO_DEVICE(n);
39+ VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
40+ size_t lens[VIRTQUEUE_MAX_SIZE];
41 struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
42 struct virtio_net_hdr_mrg_rxbuf mhdr;
43 unsigned mhdr_cnt = 0;
44- size_t offset, i, guest_offset;
45+ size_t offset, i, guest_offset, j;
46+ ssize_t err;
47
48 if (!virtio_net_can_receive(nc)) {
49 return -1;
50@@ -1699,6 +1702,12 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
51
52 total = 0;
53
54+ if (i == VIRTQUEUE_MAX_SIZE) {
55+ virtio_error(vdev, "virtio-net unexpected long buffer chain");
56+ err = size;
57+ goto err;
58+ }
59+
60 elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement));
61 if (!elem) {
62 if (i) {
63@@ -1710,7 +1719,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
64 n->guest_hdr_len, n->host_hdr_len,
65 vdev->guest_features);
66 }
67- return -1;
68+ err = -1;
69+ goto err;
70 }
71
72 if (elem->in_num < 1) {
73@@ -1718,7 +1728,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
74 "virtio-net receive queue contains no in buffers");
75 virtqueue_detach_element(q->rx_vq, elem, 0);
76 g_free(elem);
77- return -1;
78+ err = -1;
79+ goto err;
80 }
81
82 sg = elem->in_sg;
83@@ -1755,12 +1766,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
84 if (!n->mergeable_rx_bufs && offset < size) {
85 virtqueue_unpop(q->rx_vq, elem, total);
86 g_free(elem);
87- return size;
88+ err = size;
89+ goto err;
90 }
91
92- /* signal other side */
93- virtqueue_fill(q->rx_vq, elem, total, i++);
94- g_free(elem);
95+ elems[i] = elem;
96+ lens[i] = total;
97+ i++;
98 }
99
100 if (mhdr_cnt) {
101@@ -1770,10 +1782,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
102 &mhdr.num_buffers, sizeof mhdr.num_buffers);
103 }
104
105+ for (j = 0; j < i; j++) {
106+ /* signal other side */
107+ virtqueue_fill(q->rx_vq, elems[j], lens[j], j);
108+ g_free(elems[j]);
109+ }
110+
111 virtqueue_flush(q->rx_vq, i);
112 virtio_notify(vdev, q->rx_vq);
113
114 return size;
115+
116+err:
117+ for (j = 0; j < i; j++) {
118+ g_free(elems[j]);
119+ }
120+
121+ return err;
122 }
123
124 static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
125--
1262.31.1
127
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2021-3930.patch b/meta/recipes-devtools/qemu/qemu/CVE-2021-3930.patch
new file mode 100644
index 0000000000..bfbe5cee33
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/CVE-2021-3930.patch
@@ -0,0 +1,53 @@
1From cdca50eff9c38367be54f92839734ab490c8b0f7 Mon Sep 17 00:00:00 2001
2From: Mauro Matteo Cascella <mcascell@redhat.com>
3Date: Thu, 4 Nov 2021 17:31:38 +0100
4Subject: [PATCH 10/12] hw/scsi/scsi-disk: MODE_PAGE_ALLS not allowed in MODE
5 SELECT commands
6
7This avoids an off-by-one read of 'mode_sense_valid' buffer in
8hw/scsi/scsi-disk.c:mode_sense_page().
9
10Fixes: CVE-2021-3930
11Cc: qemu-stable@nongnu.org
12Reported-by: Alexander Bulekov <alxndr@bu.edu>
13Fixes: a8f4bbe2900 ("scsi-disk: store valid mode pages in a table")
14Fixes: #546
15Reported-by: Qiuhao Li <Qiuhao.Li@outlook.com>
16Signed-off-by: Mauro Matteo Cascella <mcascell@redhat.com>
17Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
18
19Upstream-Status: Backport [b3af7fdf9cc537f8f0dd3e2423d83f5c99a457e8]
20CVE: CVE-2021-3930
21
22Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com>
23---
24 hw/scsi/scsi-disk.c | 6 ++++++
25 1 file changed, 6 insertions(+)
26
27diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
28index 90841ad79..5b44ed7d8 100644
29--- a/hw/scsi/scsi-disk.c
30+++ b/hw/scsi/scsi-disk.c
31@@ -1100,6 +1100,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
32 uint8_t *p = *p_outbuf + 2;
33 int length;
34
35+ assert(page < ARRAY_SIZE(mode_sense_valid));
36 if ((mode_sense_valid[page] & (1 << s->qdev.type)) == 0) {
37 return -1;
38 }
39@@ -1441,6 +1442,11 @@ static int scsi_disk_check_mode_select(SCSIDiskState *s, int page,
40 return -1;
41 }
42
43+ /* MODE_PAGE_ALLS is only valid for MODE SENSE commands */
44+ if (page == MODE_PAGE_ALLS) {
45+ return -1;
46+ }
47+
48 p = mode_current;
49 memset(mode_current, 0, inlen + 2);
50 len = mode_sense_page(s, page, &p, 0);
51--
522.31.1
53
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2021-31799.patch b/meta/recipes-devtools/ruby/ruby/CVE-2021-31799.patch
deleted file mode 100644
index 83064e85ab..0000000000
--- a/meta/recipes-devtools/ruby/ruby/CVE-2021-31799.patch
+++ /dev/null
@@ -1,57 +0,0 @@
1From b1c73f239fe9af97de837331849f55d67c27561e Mon Sep 17 00:00:00 2001
2From: aycabta <aycabta@gmail.com>
3Date: Sun, 2 May 2021 20:52:23 +0900
4Subject: [PATCH] [ruby/rdoc] Use File.open to fix the OS Command Injection
5 vulnerability in CVE-2021-31799
6
7https://github.com/ruby/rdoc/commit/a7f5d6ab88
8
9CVE: CVE-2021-31799
10
11Upstream-Status: Backport[https://github.com/ruby/ruby/commit/b1c73f239fe9af97de837331849f55d67c27561e]
12
13Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
14---
15 lib/rdoc/rdoc.rb | 2 +-
16 test/rdoc/test_rdoc_rdoc.rb | 12 ++++++++++++
17 2 files changed, 13 insertions(+), 1 deletion(-)
18
19diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
20index 680a8612f7..904625f105 100644
21--- a/lib/rdoc/rdoc.rb
22+++ b/lib/rdoc/rdoc.rb
23@@ -444,7 +444,7 @@ def remove_unparseable files
24 files.reject do |file, *|
25 file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)$/i or
26 (file =~ /tags$/i and
27- open(file, 'rb') { |io|
28+ File.open(file, 'rb') { |io|
29 io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/
30 })
31 end
32diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb
33index 3910dd4656..a83d5a1b88 100644
34--- a/test/rdoc/test_rdoc_rdoc.rb
35+++ b/test/rdoc/test_rdoc_rdoc.rb
36@@ -456,6 +456,18 @@ def test_remove_unparseable_tags_vim
37 end
38 end
39
40+ def test_remove_unparseable_CVE_2021_31799
41+ temp_dir do
42+ file_list = ['| touch evil.txt && echo tags']
43+ file_list.each do |f|
44+ FileUtils.touch f
45+ end
46+
47+ assert_equal file_list, @rdoc.remove_unparseable(file_list)
48+ assert_equal file_list, Dir.children('.')
49+ end
50+ end
51+
52 def test_setup_output_dir
53 Dir.mktmpdir {|d|
54 path = File.join d, 'testdir'
55--
562.17.1
57
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2021-31810.patch b/meta/recipes-devtools/ruby/ruby/CVE-2021-31810.patch
deleted file mode 100644
index 69d774e0b7..0000000000
--- a/meta/recipes-devtools/ruby/ruby/CVE-2021-31810.patch
+++ /dev/null
@@ -1,258 +0,0 @@
1From 8cebc092cd18f4cfb669f66018ea8ffc6f408584 Mon Sep 17 00:00:00 2001
2From: Yusuke Endoh <mame@ruby-lang.org>
3Date: Wed, 7 Jul 2021 11:57:15 +0900
4Subject: [PATCH] Ignore IP addresses in PASV responses by default, and add new
5 option use_pasv_ip
6
7This fixes CVE-2021-31810.
8Reported by Alexandr Savca.
9
10Co-authored-by: Shugo Maeda <shugo@ruby-lang.org>
11
12CVE: CVE-2021-31810
13
14Upstream-Status: Backport
15[https://github.com/ruby/ruby/commit/bf4d05173c7cf04d8892e4b64508ecf7902717cd]
16
17Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
18---
19 lib/net/ftp.rb | 15 +++-
20 test/net/ftp/test_ftp.rb | 159 ++++++++++++++++++++++++++++++++++++++-
21 2 files changed, 170 insertions(+), 4 deletions(-)
22
23diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb
24index 88e8655..d6f5cc3 100644
25--- a/lib/net/ftp.rb
26+++ b/lib/net/ftp.rb
27@@ -98,6 +98,10 @@ module Net
28 # When +true+, the connection is in passive mode. Default: +true+.
29 attr_accessor :passive
30
31+ # When +true+, use the IP address in PASV responses. Otherwise, it uses
32+ # the same IP address for the control connection. Default: +false+.
33+ attr_accessor :use_pasv_ip
34+
35 # When +true+, all traffic to and from the server is written
36 # to +$stdout+. Default: +false+.
37 attr_accessor :debug_mode
38@@ -206,6 +210,9 @@ module Net
39 # handshake.
40 # See Net::FTP#ssl_handshake_timeout for
41 # details. Default: +nil+.
42+ # use_pasv_ip:: When +true+, use the IP address in PASV responses.
43+ # Otherwise, it uses the same IP address for the control
44+ # connection. Default: +false+.
45 # debug_mode:: When +true+, all traffic to and from the server is
46 # written to +$stdout+. Default: +false+.
47 #
48@@ -266,6 +273,7 @@ module Net
49 @open_timeout = options[:open_timeout]
50 @ssl_handshake_timeout = options[:ssl_handshake_timeout]
51 @read_timeout = options[:read_timeout] || 60
52+ @use_pasv_ip = options[:use_pasv_ip] || false
53 if host
54 connect(host, options[:port] || FTP_PORT)
55 if options[:username]
56@@ -1371,7 +1379,12 @@ module Net
57 raise FTPReplyError, resp
58 end
59 if m = /\((?<host>\d+(?:,\d+){3}),(?<port>\d+,\d+)\)/.match(resp)
60- return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"])
61+ if @use_pasv_ip
62+ host = parse_pasv_ipv4_host(m["host"])
63+ else
64+ host = @bare_sock.remote_address.ip_address
65+ end
66+ return host, parse_pasv_port(m["port"])
67 else
68 raise FTPProtoError, resp
69 end
70diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb
71index 023e794..243d4ad 100644
72--- a/test/net/ftp/test_ftp.rb
73+++ b/test/net/ftp/test_ftp.rb
74@@ -61,7 +61,7 @@ class FTPTest < Test::Unit::TestCase
75 end
76
77 def test_parse227
78- ftp = Net::FTP.new
79+ ftp = Net::FTP.new(nil, use_pasv_ip: true)
80 host, port = ftp.send(:parse227, "227 Entering Passive Mode (192,168,0,1,12,34)")
81 assert_equal("192.168.0.1", host)
82 assert_equal(3106, port)
83@@ -80,6 +80,14 @@ class FTPTest < Test::Unit::TestCase
84 assert_raise(Net::FTPProtoError) do
85 ftp.send(:parse227, "227 ) foo bar (")
86 end
87+
88+ ftp = Net::FTP.new
89+ sock = OpenStruct.new
90+ sock.remote_address = OpenStruct.new
91+ sock.remote_address.ip_address = "10.0.0.1"
92+ ftp.instance_variable_set(:@bare_sock, sock)
93+ host, port = ftp.send(:parse227, "227 Entering Passive Mode (192,168,0,1,12,34)")
94+ assert_equal("10.0.0.1", host)
95 end
96
97 def test_parse228
98@@ -2474,10 +2482,155 @@ EOF
99 end
100 end
101
102+ def test_ignore_pasv_ip
103+ commands = []
104+ binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3
105+ server = create_ftp_server(nil, "127.0.0.1") { |sock|
106+ sock.print("220 (test_ftp).\r\n")
107+ commands.push(sock.gets)
108+ sock.print("331 Please specify the password.\r\n")
109+ commands.push(sock.gets)
110+ sock.print("230 Login successful.\r\n")
111+ commands.push(sock.gets)
112+ sock.print("200 Switching to Binary mode.\r\n")
113+ line = sock.gets
114+ commands.push(line)
115+ data_server = TCPServer.new("127.0.0.1", 0)
116+ port = data_server.local_address.ip_port
117+ sock.printf("227 Entering Passive Mode (999,0,0,1,%s).\r\n",
118+ port.divmod(256).join(","))
119+ commands.push(sock.gets)
120+ sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n")
121+ conn = data_server.accept
122+ binary_data.scan(/.{1,1024}/nm) do |s|
123+ conn.print(s)
124+ end
125+ conn.shutdown(Socket::SHUT_WR)
126+ conn.read
127+ conn.close
128+ data_server.close
129+ sock.print("226 Transfer complete.\r\n")
130+ }
131+ begin
132+ begin
133+ ftp = Net::FTP.new
134+ ftp.passive = true
135+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
136+ ftp.connect("127.0.0.1", server.port)
137+ ftp.login
138+ assert_match(/\AUSER /, commands.shift)
139+ assert_match(/\APASS /, commands.shift)
140+ assert_equal("TYPE I\r\n", commands.shift)
141+ buf = ftp.getbinaryfile("foo", nil)
142+ assert_equal(binary_data, buf)
143+ assert_equal(Encoding::ASCII_8BIT, buf.encoding)
144+ assert_equal("PASV\r\n", commands.shift)
145+ assert_equal("RETR foo\r\n", commands.shift)
146+ assert_equal(nil, commands.shift)
147+ ensure
148+ ftp.close if ftp
149+ end
150+ ensure
151+ server.close
152+ end
153+ end
154+
155+ def test_use_pasv_ip
156+ commands = []
157+ binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3
158+ server = create_ftp_server(nil, "127.0.0.1") { |sock|
159+ sock.print("220 (test_ftp).\r\n")
160+ commands.push(sock.gets)
161+ sock.print("331 Please specify the password.\r\n")
162+ commands.push(sock.gets)
163+ sock.print("230 Login successful.\r\n")
164+ commands.push(sock.gets)
165+ sock.print("200 Switching to Binary mode.\r\n")
166+ line = sock.gets
167+ commands.push(line)
168+ data_server = TCPServer.new("127.0.0.1", 0)
169+ port = data_server.local_address.ip_port
170+ sock.printf("227 Entering Passive Mode (127,0,0,1,%s).\r\n",
171+ port.divmod(256).join(","))
172+ commands.push(sock.gets)
173+ sock.print("150 Opening BINARY mode data connection for foo (#{binary_data.size} bytes)\r\n")
174+ conn = data_server.accept
175+ binary_data.scan(/.{1,1024}/nm) do |s|
176+ conn.print(s)
177+ end
178+ conn.shutdown(Socket::SHUT_WR)
179+ conn.read
180+ conn.close
181+ data_server.close
182+ sock.print("226 Transfer complete.\r\n")
183+ }
184+ begin
185+ begin
186+ ftp = Net::FTP.new
187+ ftp.passive = true
188+ ftp.use_pasv_ip = true
189+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
190+ ftp.connect("127.0.0.1", server.port)
191+ ftp.login
192+ assert_match(/\AUSER /, commands.shift)
193+ assert_match(/\APASS /, commands.shift)
194+ assert_equal("TYPE I\r\n", commands.shift)
195+ buf = ftp.getbinaryfile("foo", nil)
196+ assert_equal(binary_data, buf)
197+ assert_equal(Encoding::ASCII_8BIT, buf.encoding)
198+ assert_equal("PASV\r\n", commands.shift)
199+ assert_equal("RETR foo\r\n", commands.shift)
200+ assert_equal(nil, commands.shift)
201+ ensure
202+ ftp.close if ftp
203+ end
204+ ensure
205+ server.close
206+ end
207+ end
208+
209+ def test_use_pasv_invalid_ip
210+ commands = []
211+ binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3
212+ server = create_ftp_server(nil, "127.0.0.1") { |sock|
213+ sock.print("220 (test_ftp).\r\n")
214+ commands.push(sock.gets)
215+ sock.print("331 Please specify the password.\r\n")
216+ commands.push(sock.gets)
217+ sock.print("230 Login successful.\r\n")
218+ commands.push(sock.gets)
219+ sock.print("200 Switching to Binary mode.\r\n")
220+ line = sock.gets
221+ commands.push(line)
222+ sock.print("227 Entering Passive Mode (999,0,0,1,48,57).\r\n")
223+ commands.push(sock.gets)
224+ }
225+ begin
226+ begin
227+ ftp = Net::FTP.new
228+ ftp.passive = true
229+ ftp.use_pasv_ip = true
230+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
231+ ftp.connect("127.0.0.1", server.port)
232+ ftp.login
233+ assert_match(/\AUSER /, commands.shift)
234+ assert_match(/\APASS /, commands.shift)
235+ assert_equal("TYPE I\r\n", commands.shift)
236+ assert_raise(SocketError) do
237+ ftp.getbinaryfile("foo", nil)
238+ end
239+ ensure
240+ ftp.close if ftp
241+ end
242+ ensure
243+ server.close
244+ end
245+ end
246+
247 private
248
249- def create_ftp_server(sleep_time = nil)
250- server = TCPServer.new(SERVER_ADDR, 0)
251+ def create_ftp_server(sleep_time = nil, addr = SERVER_ADDR)
252+ server = TCPServer.new(addr, 0)
253 @thread = Thread.start do
254 if sleep_time
255 sleep(sleep_time)
256--
2572.17.1
258
diff --git a/meta/recipes-devtools/ruby/ruby/CVE-2021-32066.patch b/meta/recipes-devtools/ruby/ruby/CVE-2021-32066.patch
deleted file mode 100644
index b78a74a4b5..0000000000
--- a/meta/recipes-devtools/ruby/ruby/CVE-2021-32066.patch
+++ /dev/null
@@ -1,102 +0,0 @@
1From e2ac25d0eb66de99f098d6669cf4f06796aa6256 Mon Sep 17 00:00:00 2001
2From: Shugo Maeda <shugo@ruby-lang.org>
3Date: Tue, 11 May 2021 10:31:27 +0900
4Subject: [PATCH] Fix StartTLS stripping vulnerability
5
6This fixes CVE-2021-32066.
7Reported by Alexandr Savca in <https://hackerone.com/reports/1178562>.
8
9CVE: CVE-2021-32066
10
11Upstream-Status: Backport
12[https://github.com/ruby/ruby/commit/e2ac25d0eb66de99f098d6669cf4f06796aa6256]
13
14Signed-off-by: Yi Zhao <yi.zhao@windriver.com>
15---
16 lib/net/imap.rb | 8 +++++++-
17 test/net/imap/test_imap.rb | 31 +++++++++++++++++++++++++++++++
18 2 files changed, 38 insertions(+), 1 deletion(-)
19
20diff --git a/lib/net/imap.rb b/lib/net/imap.rb
21index 505b4c8950..d45304f289 100644
22--- a/lib/net/imap.rb
23+++ b/lib/net/imap.rb
24@@ -1218,12 +1218,14 @@ def get_tagged_response(tag, cmd)
25 end
26 resp = @tagged_responses.delete(tag)
27 case resp.name
28+ when /\A(?:OK)\z/ni
29+ return resp
30 when /\A(?:NO)\z/ni
31 raise NoResponseError, resp
32 when /\A(?:BAD)\z/ni
33 raise BadResponseError, resp
34 else
35- return resp
36+ raise UnknownResponseError, resp
37 end
38 end
39
40@@ -3719,6 +3721,10 @@ class BadResponseError < ResponseError
41 class ByeResponseError < ResponseError
42 end
43
44+ # Error raised upon an unknown response from the server.
45+ class UnknownResponseError < ResponseError
46+ end
47+
48 RESPONSE_ERRORS = Hash.new(ResponseError)
49 RESPONSE_ERRORS["NO"] = NoResponseError
50 RESPONSE_ERRORS["BAD"] = BadResponseError
51diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
52index 8b924b524e..85fb71d440 100644
53--- a/test/net/imap/test_imap.rb
54+++ b/test/net/imap/test_imap.rb
55@@ -127,6 +127,16 @@ def test_starttls
56 imap.disconnect
57 end
58 end
59+
60+ def test_starttls_stripping
61+ starttls_stripping_test do |port|
62+ imap = Net::IMAP.new("localhost", :port => port)
63+ assert_raise(Net::IMAP::UnknownResponseError) do
64+ imap.starttls(:ca_file => CA_FILE)
65+ end
66+ imap
67+ end
68+ end
69 end
70
71 def start_server
72@@ -834,6 +844,27 @@ def starttls_test
73 end
74 end
75
76+ def starttls_stripping_test
77+ server = create_tcp_server
78+ port = server.addr[1]
79+ start_server do
80+ sock = server.accept
81+ begin
82+ sock.print("* OK test server\r\n")
83+ sock.gets
84+ sock.print("RUBY0001 BUG unhandled command\r\n")
85+ ensure
86+ sock.close
87+ server.close
88+ end
89+ end
90+ begin
91+ imap = yield(port)
92+ ensure
93+ imap.disconnect if imap && !imap.disconnected?
94+ end
95+ end
96+
97 def create_tcp_server
98 return TCPServer.new(server_addr, 0)
99 end
100--
1012.25.1
102
diff --git a/meta/recipes-devtools/ruby/ruby_3.0.1.bb b/meta/recipes-devtools/ruby/ruby_3.0.3.bb
index a348946972..a781f69534 100644
--- a/meta/recipes-devtools/ruby/ruby_3.0.1.bb
+++ b/meta/recipes-devtools/ruby/ruby_3.0.3.bb
@@ -6,16 +6,13 @@ SRC_URI += " \
6 file://remove_has_include_macros.patch \ 6 file://remove_has_include_macros.patch \
7 file://run-ptest \ 7 file://run-ptest \
8 file://0001-template-Makefile.in-do-not-write-host-cross-cc-item.patch \ 8 file://0001-template-Makefile.in-do-not-write-host-cross-cc-item.patch \
9 file://CVE-2021-31810.patch \
10 file://CVE-2021-32066.patch \
11 file://CVE-2021-31799.patch \
12 file://0003-rdoc-build-reproducible-documentation.patch \ 9 file://0003-rdoc-build-reproducible-documentation.patch \
13 file://0004-lib-mkmf.rb-sort-list-of-object-files-in-generated-M.patch \ 10 file://0004-lib-mkmf.rb-sort-list-of-object-files-in-generated-M.patch \
14 file://0005-Mark-Gemspec-reproducible-change-fixing-784225-too.patch \ 11 file://0005-Mark-Gemspec-reproducible-change-fixing-784225-too.patch \
15 file://0006-Make-gemspecs-reproducible.patch \ 12 file://0006-Make-gemspecs-reproducible.patch \
16 " 13 "
17 14
18SRC_URI[sha256sum] = "369825db2199f6aeef16b408df6a04ebaddb664fb9af0ec8c686b0ce7ab77727" 15SRC_URI[sha256sum] = "3586861cb2df56970287f0fd83f274bd92058872d830d15570b36def7f1a92ac"
19 16
20PACKAGECONFIG ??= "" 17PACKAGECONFIG ??= ""
21PACKAGECONFIG += "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)}" 18PACKAGECONFIG += "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)}"
@@ -81,8 +78,6 @@ do_install_ptest () {
81 -i ${D}${PTEST_PATH}/test/erb/test_erb_command.rb 78 -i ${D}${PTEST_PATH}/test/erb/test_erb_command.rb
82 79
83 cp -r ${S}/include ${D}/${libdir}/ruby/ 80 cp -r ${S}/include ${D}/${libdir}/ruby/
84 test_case_rb=`grep rubygems/test_case.rb ${B}/.installed.list`
85 sed -i -e 's:../../../test/:../../../ptest/test/:g' ${D}/$test_case_rb
86} 81}
87 82
88PACKAGES =+ "${PN}-ri-docs ${PN}-rdoc" 83PACKAGES =+ "${PN}-ri-docs ${PN}-rdoc"
diff --git a/meta/recipes-devtools/unfs3/unfs3_git.bb b/meta/recipes-devtools/unfs3/unfs3_git.bb
index bcaa4e2822..06148005cf 100644
--- a/meta/recipes-devtools/unfs3/unfs3_git.bb
+++ b/meta/recipes-devtools/unfs3/unfs3_git.bb
@@ -37,7 +37,7 @@ BBCLASSEXTEND = "native nativesdk"
37inherit autotools 37inherit autotools
38EXTRA_OECONF_append_class-native = " --sbindir=${bindir}" 38EXTRA_OECONF_append_class-native = " --sbindir=${bindir}"
39CFLAGS_append = " -I${STAGING_INCDIR}/tirpc" 39CFLAGS_append = " -I${STAGING_INCDIR}/tirpc"
40LDFLAGS_append = " -ltirpc" 40EXTRA_OECONF_append = " LIBS=-ltirpc"
41 41
42# Turn off these header detects else the inode search 42# Turn off these header detects else the inode search
43# will walk entire file systems and this is a real problem 43# will walk entire file systems and this is a real problem
diff --git a/meta/recipes-extended/asciidoc/asciidoc_9.1.0.bb b/meta/recipes-extended/asciidoc/asciidoc_9.1.0.bb
index 523bf33f42..3869abee59 100644
--- a/meta/recipes-extended/asciidoc/asciidoc_9.1.0.bb
+++ b/meta/recipes-extended/asciidoc/asciidoc_9.1.0.bb
@@ -8,7 +8,7 @@ LICENSE = "GPLv2"
8LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=4e5d1baf6f20559e3bec172226a47e4e \ 8LIC_FILES_CHKSUM = "file://COPYRIGHT;md5=4e5d1baf6f20559e3bec172226a47e4e \
9 file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263 " 9 file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263 "
10 10
11SRC_URI = "git://github.com/asciidoc/asciidoc-py3;protocol=https;branch=9.x" 11SRC_URI = "git://github.com/asciidoc/asciidoc-py;protocol=https;branch=9.x"
12SRCREV = "9705d428439530104ce55d0ba12e8ef9d1b57ad1" 12SRCREV = "9705d428439530104ce55d0ba12e8ef9d1b57ad1"
13 13
14DEPENDS = "libxml2-native libxslt-native docbook-xml-dtd4-native docbook-xsl-stylesheets-native" 14DEPENDS = "libxml2-native libxslt-native docbook-xml-dtd4-native docbook-xsl-stylesheets-native"
diff --git a/meta/recipes-extended/cups/cups.inc b/meta/recipes-extended/cups/cups.inc
index beee614828..a667d1a142 100644
--- a/meta/recipes-extended/cups/cups.inc
+++ b/meta/recipes-extended/cups/cups.inc
@@ -44,7 +44,7 @@ PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'zeroconf', 'avahi',
44PACKAGECONFIG[avahi] = "--enable-avahi,--disable-avahi,avahi" 44PACKAGECONFIG[avahi] = "--enable-avahi,--disable-avahi,avahi"
45PACKAGECONFIG[acl] = "--enable-acl,--disable-acl,acl" 45PACKAGECONFIG[acl] = "--enable-acl,--disable-acl,acl"
46PACKAGECONFIG[pam] = "--enable-pam --with-pam-module=unix, --disable-pam, libpam" 46PACKAGECONFIG[pam] = "--enable-pam --with-pam-module=unix, --disable-pam, libpam"
47PACKAGECONFIG[systemd] = "--with-systemd=${systemd_system_unitdir},--without-systemd,systemd" 47PACKAGECONFIG[systemd] = "--with-systemd=${systemd_system_unitdir},--disable-systemd,systemd"
48PACKAGECONFIG[xinetd] = "--with-xinetd=${sysconfdir}/xinetd.d,--without-xinetd,xinetd" 48PACKAGECONFIG[xinetd] = "--with-xinetd=${sysconfdir}/xinetd.d,--without-xinetd,xinetd"
49 49
50EXTRA_OECONF = " \ 50EXTRA_OECONF = " \
diff --git a/meta/recipes-extended/ghostscript/ghostscript/CVE-2021-45949.patch b/meta/recipes-extended/ghostscript/ghostscript/CVE-2021-45949.patch
new file mode 100644
index 0000000000..f312f89e04
--- /dev/null
+++ b/meta/recipes-extended/ghostscript/ghostscript/CVE-2021-45949.patch
@@ -0,0 +1,65 @@
1From 6643ff0cb837db3eade489ffff21e3e92eee2ae0 Mon Sep 17 00:00:00 2001
2From: Chris Liddell <chris.liddell@artifex.com>
3Date: Fri, 28 Jan 2022 08:21:19 +0000
4Subject: [PATCH] [PATCH] Bug 703902: Fix op stack management in
5 sampled_data_continue()
6
7Replace pop() (which does no checking, and doesn't handle stack extension
8blocks) with ref_stack_pop() which does do all that.
9
10We still use pop() in one case (it's faster), but we have to later use
11ref_stack_pop() before calling sampled_data_sample() which also accesses the
12op stack.
13
14Fixes:
15https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=34675
16
17Upstream-Status: Backported [https://git.ghostscript.com/?p=ghostpdl.git;a=commit;h=2a3129365d3bc0d4a41f107ef175920d1505d1f7]
18CVE: CVE-2021-45949
19Signed-off-by: Minjae Kim <flowergom@gmail.com>
20---
21 psi/zfsample.c | 13 ++++++++-----
22 1 file changed, 8 insertions(+), 5 deletions(-)
23
24diff --git a/psi/zfsample.c b/psi/zfsample.c
25index 0023fa4..f84671f 100644
26--- a/psi/zfsample.c
27+++ b/psi/zfsample.c
28@@ -534,14 +534,17 @@ sampled_data_continue(i_ctx_t *i_ctx_p)
29 data_ptr[bps * i + j] = (byte)(cv >> ((bps - 1 - j) * 8)); /* MSB first */
30 }
31 pop(num_out); /* Move op to base of result values */
32-
33+ /* From here on, we have to use ref_stack_pop() rather than pop()
34+ so that it handles stack extension blocks properly, before calling
35+ sampled_data_sample() which also uses the op stack.
36+ */
37 /* Check if we are done collecting data. */
38
39 if (increment_cube_indexes(params, penum->indexes)) {
40 if (stack_depth_adjust == 0)
41- pop(O_STACK_PAD); /* Remove spare stack space */
42+ ref_stack_pop(&o_stack, O_STACK_PAD); /* Remove spare stack space */
43 else
44- pop(stack_depth_adjust - num_out);
45+ ref_stack_pop(&o_stack, stack_depth_adjust - num_out);
46 /* Execute the closing procedure, if given */
47 code = 0;
48 if (esp_finish_proc != 0)
49@@ -554,11 +557,11 @@ sampled_data_continue(i_ctx_t *i_ctx_p)
50 if ((O_STACK_PAD - stack_depth_adjust) < 0) {
51 stack_depth_adjust = -(O_STACK_PAD - stack_depth_adjust);
52 check_op(stack_depth_adjust);
53- pop(stack_depth_adjust);
54+ ref_stack_pop(&o_stack, stack_depth_adjust);
55 }
56 else {
57 check_ostack(O_STACK_PAD - stack_depth_adjust);
58- push(O_STACK_PAD - stack_depth_adjust);
59+ ref_stack_push(&o_stack, O_STACK_PAD - stack_depth_adjust);
60 for (i=0;i<O_STACK_PAD - stack_depth_adjust;i++)
61 make_null(op - i);
62 }
63--
642.17.1
65
diff --git a/meta/recipes-extended/ghostscript/ghostscript/check-stack-limits-after-function-evalution.patch b/meta/recipes-extended/ghostscript/ghostscript/check-stack-limits-after-function-evalution.patch
new file mode 100644
index 0000000000..722bab4ddb
--- /dev/null
+++ b/meta/recipes-extended/ghostscript/ghostscript/check-stack-limits-after-function-evalution.patch
@@ -0,0 +1,51 @@
1From 7861fcad13c497728189feafb41cd57b5b50ea25 Mon Sep 17 00:00:00 2001
2From: Chris Liddell <chris.liddell@artifex.com>
3Date: Fri, 12 Feb 2021 10:34:23 +0000
4Subject: [PATCH] oss-fuzz 30715: Check stack limits after function evaluation.
5
6During function result sampling, after the callout to the Postscript
7interpreter, make sure there is enough stack space available before pushing
8or popping entries.
9
10In thise case, the Postscript procedure for the "function" is totally invalid
11(as a function), and leaves the op stack in an unrecoverable state (as far as
12function evaluation is concerned). We end up popping more entries off the
13stack than are available.
14
15To cope, add in stack limit checking to throw an appropriate error when this
16happens.
17
18Upstream-Status: Backported [https://git.ghostscript.com/?p=ghostpdl.git;a=patch;h=7861fcad13c497728189feafb41cd57b5b50ea25]
19Signed-off-by: Minjae Kim <flowergom@gmail.com>
20---
21 psi/zfsample.c | 14 +++++++++++---
22 1 file changed, 11 insertions(+), 3 deletions(-)
23
24diff --git a/psi/zfsample.c b/psi/zfsample.c
25index 290809405..652ae02c6 100644
26--- a/psi/zfsample.c
27+++ b/psi/zfsample.c
28@@ -551,9 +551,17 @@ sampled_data_continue(i_ctx_t *i_ctx_p)
29 } else {
30 if (stack_depth_adjust) {
31 stack_depth_adjust -= num_out;
32- push(O_STACK_PAD - stack_depth_adjust);
33- for (i=0;i<O_STACK_PAD - stack_depth_adjust;i++)
34- make_null(op - i);
35+ if ((O_STACK_PAD - stack_depth_adjust) < 0) {
36+ stack_depth_adjust = -(O_STACK_PAD - stack_depth_adjust);
37+ check_op(stack_depth_adjust);
38+ pop(stack_depth_adjust);
39+ }
40+ else {
41+ check_ostack(O_STACK_PAD - stack_depth_adjust);
42+ push(O_STACK_PAD - stack_depth_adjust);
43+ for (i=0;i<O_STACK_PAD - stack_depth_adjust;i++)
44+ make_null(op - i);
45+ }
46 }
47 }
48
49--
502.25.1
51
diff --git a/meta/recipes-extended/ghostscript/ghostscript_9.53.3.bb b/meta/recipes-extended/ghostscript/ghostscript_9.53.3.bb
index 216822478f..958a88e968 100644
--- a/meta/recipes-extended/ghostscript/ghostscript_9.53.3.bb
+++ b/meta/recipes-extended/ghostscript/ghostscript_9.53.3.bb
@@ -34,6 +34,8 @@ SRC_URI_BASE = "https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/d
34 file://avoid-host-contamination.patch \ 34 file://avoid-host-contamination.patch \
35 file://mkdir-p.patch \ 35 file://mkdir-p.patch \
36 file://0001-Bug-704342-Include-device-specifier-strings-in-acces.patch \ 36 file://0001-Bug-704342-Include-device-specifier-strings-in-acces.patch \
37 file://check-stack-limits-after-function-evalution.patch \
38 file://CVE-2021-45949.patch \
37" 39"
38 40
39SRC_URI = "${SRC_URI_BASE} \ 41SRC_URI = "${SRC_URI_BASE} \
diff --git a/meta/recipes-extended/libarchive/libarchive_3.5.1.bb b/meta/recipes-extended/libarchive/libarchive_3.5.3.bb
index 1387b69066..92bb223784 100644
--- a/meta/recipes-extended/libarchive/libarchive_3.5.1.bb
+++ b/meta/recipes-extended/libarchive/libarchive_3.5.3.bb
@@ -34,7 +34,7 @@ EXTRA_OECONF += "--enable-largefile"
34 34
35SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz" 35SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz"
36 36
37SRC_URI[sha256sum] = "9015d109ec00bb9ae1a384b172bf2fc1dff41e2c66e5a9eeddf933af9db37f5a" 37SRC_URI[sha256sum] = "72788e5f58d16febddfa262a5215e05fc9c79f2670f641ac039e6df44330ef51"
38 38
39inherit autotools update-alternatives pkgconfig 39inherit autotools update-alternatives pkgconfig
40 40
diff --git a/meta/recipes-extended/lighttpd/lighttpd/0001-mod_extforward-fix-out-of-bounds-OOB-write-fixes-313.patch b/meta/recipes-extended/lighttpd/lighttpd/0001-mod_extforward-fix-out-of-bounds-OOB-write-fixes-313.patch
new file mode 100644
index 0000000000..f4e93d1065
--- /dev/null
+++ b/meta/recipes-extended/lighttpd/lighttpd/0001-mod_extforward-fix-out-of-bounds-OOB-write-fixes-313.patch
@@ -0,0 +1,97 @@
1Upstream-Status: Backport
2CVE: CVE-2022-22707
3Signed-off-by: Ross Burton <ross.burton@arm.com>
4
5From 27103f3f8b1a2857aa45b889e775435f7daf141f Mon Sep 17 00:00:00 2001
6From: povcfe <povcfe@qq.com>
7Date: Wed, 5 Jan 2022 11:11:09 +0000
8Subject: [PATCH] [mod_extforward] fix out-of-bounds (OOB) write (fixes #3134)
9
10(thx povcfe)
11
12(edited: gstrauss)
13
14There is a potential remote denial of service in lighttpd mod_extforward
15under specific, non-default and uncommon 32-bit lighttpd mod_extforward
16configurations.
17
18Under specific, non-default and uncommon lighttpd mod_extforward
19configurations, a remote attacker can trigger a 4-byte out-of-bounds
20write of value '-1' to the stack. This is not believed to be exploitable
21in any way beyond triggering a crash of the lighttpd server on systems
22where the lighttpd server has been built 32-bit and with compiler flags
23which enable a stack canary -- gcc/clang -fstack-protector-strong or
24-fstack-protector-all, but bug not visible with only -fstack-protector.
25
26With standard lighttpd builds using -O2 optimization on 64-bit x86_64,
27this bug has not been observed to cause adverse behavior, even with
28gcc/clang -fstack-protector-strong.
29
30For the bug to be reachable, the user must be using a non-default
31lighttpd configuration which enables mod_extforward and configures
32mod_extforward to accept and parse the "Forwarded" header from a trusted
33proxy. At this time, support for RFC7239 Forwarded is not common in CDN
34providers or popular web server reverse proxies. It bears repeating that
35for the user to desire to configure lighttpd mod_extforward to accept
36"Forwarded", the user must also be using a trusted proxy (in front of
37lighttpd) which understands and actively modifies the "Forwarded" header
38sent to lighttpd.
39
40lighttpd natively supports RFC7239 "Forwarded"
41hiawatha natively supports RFC7239 "Forwarded"
42
43nginx can be manually configured to add a "Forwarded" header
44https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
45
46A 64-bit build of lighttpd on x86_64 (not known to be affected by bug)
47in front of another 32-bit lighttpd will detect and reject a malicious
48"Forwarded" request header, thereby thwarting an attempt to trigger
49this bug in an upstream 32-bit lighttpd.
50
51The following servers currently do not natively support RFC7239 Forwarded:
52nginx
53apache2
54caddy
55node.js
56haproxy
57squid
58varnish-cache
59litespeed
60
61Given the general dearth of support for RFC7239 Forwarded in popular
62CDNs and web server reverse proxies, and given the prerequisites in
63lighttpd mod_extforward needed to reach this bug, the number of lighttpd
64servers vulnerable to this bug is estimated to be vanishingly small.
65Large systems using reverse proxies are likely running 64-bit lighttpd,
66which is not known to be adversely affected by this bug.
67
68In the future, it is desirable for more servers to implement RFC7239
69Forwarded. lighttpd developers would like to thank povcfe for reporting
70this bug so that it can be fixed before more CDNs and web servers
71implement RFC7239 Forwarded.
72
73x-ref:
74 "mod_extforward plugin has out-of-bounds (OOB) write of 4-byte -1"
75 https://redmine.lighttpd.net/issues/3134
76 (not yet written or published)
77 CVE-2022-22707
78---
79 src/mod_extforward.c | 2 +-
80 1 file changed, 1 insertion(+), 1 deletion(-)
81
82diff --git a/src/mod_extforward.c b/src/mod_extforward.c
83index ba957e04..fdaef7f6 100644
84--- a/src/mod_extforward.c
85+++ b/src/mod_extforward.c
86@@ -715,7 +715,7 @@ static handler_t mod_extforward_Forwarded (request_st * const r, plugin_data * c
87 while (s[i] == ' ' || s[i] == '\t') ++i;
88 if (s[i] == ';') { ++i; continue; }
89 if (s[i] == ',') {
90- if (j >= (int)(sizeof(offsets)/sizeof(int))) break;
91+ if (j >= (int)(sizeof(offsets)/sizeof(int))-1) break;
92 offsets[++j] = -1; /*("offset" separating params from next proxy)*/
93 ++i;
94 continue;
95--
962.25.1
97
diff --git a/meta/recipes-extended/lighttpd/lighttpd_1.4.59.bb b/meta/recipes-extended/lighttpd/lighttpd_1.4.59.bb
index cf7f478915..73443f77b4 100644
--- a/meta/recipes-extended/lighttpd/lighttpd_1.4.59.bb
+++ b/meta/recipes-extended/lighttpd/lighttpd_1.4.59.bb
@@ -14,6 +14,7 @@ RRECOMMENDS_${PN} = "lighttpd-module-access \
14 lighttpd-module-accesslog" 14 lighttpd-module-accesslog"
15 15
16SRC_URI = "http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-${PV}.tar.xz \ 16SRC_URI = "http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-${PV}.tar.xz \
17 file://0001-mod_extforward-fix-out-of-bounds-OOB-write-fixes-313.patch \
17 file://index.html.lighttpd \ 18 file://index.html.lighttpd \
18 file://lighttpd.conf \ 19 file://lighttpd.conf \
19 file://lighttpd \ 20 file://lighttpd \
diff --git a/meta/recipes-extended/mc/files/0001-Ticket-4200-fix-FTBFS-with-ncurses-build-with-disabl.patch b/meta/recipes-extended/mc/files/0001-Ticket-4200-fix-FTBFS-with-ncurses-build-with-disabl.patch
new file mode 100644
index 0000000000..408473664f
--- /dev/null
+++ b/meta/recipes-extended/mc/files/0001-Ticket-4200-fix-FTBFS-with-ncurses-build-with-disabl.patch
@@ -0,0 +1,87 @@
1From e7bbf72544ab62db9c92bfe7bd1155227e78c621 Mon Sep 17 00:00:00 2001
2From: Andrew Borodin <aborodin@vmail.ru>
3Date: Sat, 28 Aug 2021 11:46:53 +0300
4Subject: [PATCH] Ticket #4200: fix FTBFS with ncurses build with
5 --disable-widec.
6
7Upstream-Status: Accepted [https://github.com/MidnightCommander/mc/commit/e7bbf72544]
8Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
9---
10 lib/tty/tty-ncurses.c | 8 ++++++++
11 lib/tty/tty-ncurses.h | 5 +++++
12 lib/tty/tty-slang.h | 2 ++
13 src/filemanager/boxes.c | 2 ++
14 4 files changed, 17 insertions(+)
15
16diff --git a/lib/tty/tty-ncurses.c b/lib/tty/tty-ncurses.c
17index f619c0a7bf31..13058a624208 100644
18--- a/lib/tty/tty-ncurses.c
19+++ b/lib/tty/tty-ncurses.c
20@@ -560,6 +560,7 @@ tty_fill_region (int y, int x, int rows, int cols, unsigned char ch)
21 void
22 tty_colorize_area (int y, int x, int rows, int cols, int color)
23 {
24+#ifdef ENABLE_SHADOWS
25 cchar_t *ctext;
26 wchar_t wch[10]; /* TODO not sure if the length is correct */
27 attr_t attrs;
28@@ -585,6 +586,13 @@ tty_colorize_area (int y, int x, int rows, int cols, int color)
29 }
30
31 g_free (ctext);
32+#else
33+ (void) y;
34+ (void) x;
35+ (void) rows;
36+ (void) cols;
37+ (void) color;
38+#endif /* ENABLE_SHADOWS */
39 }
40
41 /* --------------------------------------------------------------------------------------------- */
42diff --git a/lib/tty/tty-ncurses.h b/lib/tty/tty-ncurses.h
43index d75df9533ab9..8feb17ccd045 100644
44--- a/lib/tty/tty-ncurses.h
45+++ b/lib/tty/tty-ncurses.h
46@@ -30,6 +30,11 @@
47 #define NCURSES_CONST const
48 #endif
49
50+/* do not draw shadows if NCurses is built with --disable-widec */
51+#if defined(NCURSES_WIDECHAR) && NCURSES_WIDECHAR
52+#define ENABLE_SHADOWS 1
53+#endif
54+
55 /*** typedefs(not structures) and defined constants **********************************************/
56
57 /*** enums ***************************************************************************************/
58diff --git a/lib/tty/tty-slang.h b/lib/tty/tty-slang.h
59index 5b12c6512853..eeaade388af4 100644
60--- a/lib/tty/tty-slang.h
61+++ b/lib/tty/tty-slang.h
62@@ -23,6 +23,8 @@
63 #define COLS SLtt_Screen_Cols
64 #define LINES SLtt_Screen_Rows
65
66+#define ENABLE_SHADOWS 1
67+
68 /*** enums ***************************************************************************************/
69
70 enum
71diff --git a/src/filemanager/boxes.c b/src/filemanager/boxes.c
72index 3eb525be4a9b..98df5ff2ed9a 100644
73--- a/src/filemanager/boxes.c
74+++ b/src/filemanager/boxes.c
75@@ -280,7 +280,9 @@ appearance_box_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm
76 switch (msg)
77 {
78 case MSG_INIT:
79+#ifdef ENABLE_SHADOWS
80 if (!tty_use_colors ())
81+#endif
82 {
83 Widget *shadow;
84
85--
862.34.1
87
diff --git a/meta/recipes-extended/mc/mc_4.8.26.bb b/meta/recipes-extended/mc/mc_4.8.26.bb
index 6bc7e6e8e1..906778400e 100644
--- a/meta/recipes-extended/mc/mc_4.8.26.bb
+++ b/meta/recipes-extended/mc/mc_4.8.26.bb
@@ -12,6 +12,7 @@ SRC_URI = "http://www.midnight-commander.org/downloads/${BPN}-${PV}.tar.bz2 \
12 file://0001-mc-replace-perl-w-with-use-warnings.patch \ 12 file://0001-mc-replace-perl-w-with-use-warnings.patch \
13 file://nomandate.patch \ 13 file://nomandate.patch \
14 file://CVE-2021-36370.patch \ 14 file://CVE-2021-36370.patch \
15 file://0001-Ticket-4200-fix-FTBFS-with-ncurses-build-with-disabl.patch \
15 " 16 "
16SRC_URI[sha256sum] = "9d6358d0a351a455a1410aab57f33b6b48b0fcf31344b9a10b0ff497595979d1" 17SRC_URI[sha256sum] = "9d6358d0a351a455a1410aab57f33b6b48b0fcf31344b9a10b0ff497595979d1"
17 18
@@ -24,7 +25,9 @@ PACKAGECONFIG ??= ""
24PACKAGECONFIG[smb] = "--enable-vfs-smb,--disable-vfs-smb,samba," 25PACKAGECONFIG[smb] = "--enable-vfs-smb,--disable-vfs-smb,samba,"
25PACKAGECONFIG[sftp] = "--enable-vfs-sftp,--disable-vfs-sftp,libssh2," 26PACKAGECONFIG[sftp] = "--enable-vfs-sftp,--disable-vfs-sftp,libssh2,"
26 27
27CFLAGS_append_libc-musl = ' -DNCURSES_WIDECHAR=1 ' 28# enable NCURSES_WIDECHAR=1 only if ENABLE_WIDEC has not been explicitly disabled (e.g. by the distro config).
29# When compiling against the ncurses library, NCURSES_WIDECHAR needs to explicitly set to 0 in this case.
30CFLAGS_append_libc-musl = "${@' -DNCURSES_WIDECHAR=1' if bb.utils.to_boolean((d.getVar('ENABLE_WIDEC') or 'True')) else ' -DNCURSES_WIDECHAR=0'}"
28EXTRA_OECONF = "--with-screen=ncurses --without-gpm-mouse --without-x --disable-configure-args" 31EXTRA_OECONF = "--with-screen=ncurses --without-gpm-mouse --without-x --disable-configure-args"
29 32
30CACHED_CONFIGUREVARS += "ac_cv_path_PERL='/usr/bin/env perl'" 33CACHED_CONFIGUREVARS += "ac_cv_path_PERL='/usr/bin/env perl'"
diff --git a/meta/recipes-extended/pigz/files/0001-Fix-bug-when-combining-l-with-d.patch b/meta/recipes-extended/pigz/files/0001-Fix-bug-when-combining-l-with-d.patch
new file mode 100644
index 0000000000..9c301f2054
--- /dev/null
+++ b/meta/recipes-extended/pigz/files/0001-Fix-bug-when-combining-l-with-d.patch
@@ -0,0 +1,50 @@
1From 65986f3d12d434b9bc428ceb6fcb1f6eeeb2c47d Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Mon, 17 Jan 2022 15:36:56 +0800
4Subject: [PATCH] Fix bug when combining -l with -d.
5
6Though it makes no sense to do pigz -ld, that is implicit when
7doing unpigz -l. This commit fixes a bug for that combination.
8
9Upstream-Status: Backport [https://github.com/madler/pigz/commit/326bba44aa102c707dd6ebcd2fc3f413b3119db0]
10
11Signed-off-by: Changqing Li <changqing.li@windriver.com>
12---
13 pigz.c | 14 +++++++-------
14 1 file changed, 7 insertions(+), 7 deletions(-)
15
16diff --git a/pigz.c b/pigz.c
17index f90157f..d648216 100644
18--- a/pigz.c
19+++ b/pigz.c
20@@ -4007,6 +4007,13 @@ local void process(char *path) {
21 }
22 SET_BINARY_MODE(g.ind);
23
24+ // if requested, just list information about the input file
25+ if (g.list && g.decode != 2) {
26+ list_info();
27+ load_end();
28+ return;
29+ }
30+
31 // if decoding or testing, try to read gzip header
32 if (g.decode) {
33 in_init();
34@@ -4048,13 +4055,6 @@ local void process(char *path) {
35 }
36 }
37
38- // if requested, just list information about input file
39- if (g.list) {
40- list_info();
41- load_end();
42- return;
43- }
44-
45 // create output file out, descriptor outd
46 if (path == NULL || g.pipeout) {
47 // write to stdout
48--
492.17.1
50
diff --git a/meta/recipes-extended/pigz/pigz_2.6.bb b/meta/recipes-extended/pigz/pigz_2.6.bb
index 05be9b733f..5c0aab55a7 100644
--- a/meta/recipes-extended/pigz/pigz_2.6.bb
+++ b/meta/recipes-extended/pigz/pigz_2.6.bb
@@ -8,7 +8,8 @@ SECTION = "console/utils"
8LICENSE = "Zlib & Apache-2.0" 8LICENSE = "Zlib & Apache-2.0"
9LIC_FILES_CHKSUM = "file://pigz.c;md5=9ae6dee8ceba9610596ed0ada493d142;beginline=7;endline=21" 9LIC_FILES_CHKSUM = "file://pigz.c;md5=9ae6dee8ceba9610596ed0ada493d142;beginline=7;endline=21"
10 10
11SRC_URI = "http://zlib.net/${BPN}/fossils/${BP}.tar.gz" 11SRC_URI = "http://zlib.net/${BPN}/fossils/${BP}.tar.gz \
12 file://0001-Fix-bug-when-combining-l-with-d.patch"
12SRC_URI[sha256sum] = "2eed7b0d7449d1d70903f2a62cd6005d262eb3a8c9e98687bc8cbb5809db2a7d" 13SRC_URI[sha256sum] = "2eed7b0d7449d1d70903f2a62cd6005d262eb3a8c9e98687bc8cbb5809db2a7d"
13PROVIDES_class-native += "gzip-native" 14PROVIDES_class-native += "gzip-native"
14 15
diff --git a/meta/recipes-extended/zip/zip-3.0/0001-configure-use-correct-CPP.patch b/meta/recipes-extended/zip/zip-3.0/0001-configure-use-correct-CPP.patch
new file mode 100644
index 0000000000..02253f968c
--- /dev/null
+++ b/meta/recipes-extended/zip/zip-3.0/0001-configure-use-correct-CPP.patch
@@ -0,0 +1,47 @@
1From 7a2729ee7f5d9b9d4a0d9b83fe641a2ab03c4ee0 Mon Sep 17 00:00:00 2001
2From: Joe Slater <joe.slater@windriver.com>
3Date: Thu, 24 Feb 2022 17:36:59 -0800
4Subject: [PATCH 1/2] configure: use correct CPP
5
6configure uses CPP to test that two assembler routines
7can be built. Unfortunately, it will use /usr/bin/cpp
8if it exists, invalidating the tests. We use the $CC
9passed to configure.
10
11Upstream-Status: Inappropriate [openembedded specific]
12
13Signed-off-by: Joe Slater <joe.slater@windriver.com>
14---
15 unix/configure | 15 +++++++++------
16 1 file changed, 9 insertions(+), 6 deletions(-)
17
18diff --git a/unix/configure b/unix/configure
19index 73ba803..7e21070 100644
20--- a/unix/configure
21+++ b/unix/configure
22@@ -220,13 +220,16 @@ fi
23 echo Check for the C preprocessor
24 # on SVR4, cc -E does not produce correct assembler files. Need /lib/cpp.
25 CPP="${CC} -E"
26+
27+# We should not change CPP for yocto builds.
28+#
29 # solaris as(1) needs -P, maybe others as well ?
30-[ -f /usr/ccs/lib/cpp ] && CPP="/usr/ccs/lib/cpp -P"
31-[ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp
32-[ -f /lib/cpp ] && CPP=/lib/cpp
33-[ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp
34-[ -f /xenix ] && CPP="${CC} -E"
35-[ -f /lynx.os ] && CPP="${CC} -E"
36+# [ -f /usr/ccs/lib/cpp ] && CPP="/usr/ccs/lib/cpp -P"
37+# [ -f /usr/lib/cpp ] && CPP=/usr/lib/cpp
38+# [ -f /lib/cpp ] && CPP=/lib/cpp
39+# [ -f /usr/bin/cpp ] && CPP=/usr/bin/cpp
40+# [ -f /xenix ] && CPP="${CC} -E"
41+# [ -f /lynx.os ] && CPP="${CC} -E"
42
43 echo "#include <stdio.h>" > conftest.c
44 $CPP conftest.c >/dev/null 2>/dev/null || CPP="${CC} -E"
45--
462.24.1
47
diff --git a/meta/recipes-extended/zip/zip-3.0/0002-configure-support-PIC-code-build.patch b/meta/recipes-extended/zip/zip-3.0/0002-configure-support-PIC-code-build.patch
new file mode 100644
index 0000000000..6e0879616a
--- /dev/null
+++ b/meta/recipes-extended/zip/zip-3.0/0002-configure-support-PIC-code-build.patch
@@ -0,0 +1,34 @@
1From b0492506d2c28581193906e9d260d4f0451e2c39 Mon Sep 17 00:00:00 2001
2From: Joe Slater <joe.slater@windriver.com>
3Date: Thu, 24 Feb 2022 17:46:03 -0800
4Subject: [PATCH 2/2] configure: support PIC code build
5
6Disable building match.S. The code requires
7relocation in .text.
8
9Upstream-Status: Inappropriate [openembedded specific]
10
11Signed-off-by: Joe Slater <joe.slater@windriver.com>
12---
13 unix/configure | 5 +++--
14 1 file changed, 3 insertions(+), 2 deletions(-)
15
16diff --git a/unix/configure b/unix/configure
17index 7e21070..1bc698b 100644
18--- a/unix/configure
19+++ b/unix/configure
20@@ -242,8 +242,9 @@ if eval "$CPP match.S > _match.s 2>/dev/null"; then
21 if test ! -s _match.s || grep error < _match.s > /dev/null; then
22 :
23 elif eval "$CC -c _match.s >/dev/null 2>/dev/null" && [ -f _match.o ]; then
24- CFLAGS="${CFLAGS} -DASMV"
25- OBJA="match.o"
26+ # disable match.S for PIC code
27+ # CFLAGS="${CFLAGS} -DASMV"
28+ # OBJA="match.o"
29 echo "int foo() { return 0;}" > conftest.c
30 $CC -c conftest.c >/dev/null 2>/dev/null
31 echo Check if compiler generates underlines
32--
332.24.1
34
diff --git a/meta/recipes-extended/zip/zip_3.0.bb b/meta/recipes-extended/zip/zip_3.0.bb
index 18b5d8648e..f8e0b6e259 100644
--- a/meta/recipes-extended/zip/zip_3.0.bb
+++ b/meta/recipes-extended/zip/zip_3.0.bb
@@ -14,6 +14,8 @@ SRC_URI = "${SOURCEFORGE_MIRROR}/infozip/Zip%203.x%20%28latest%29/3.0/zip30.tar.
14 file://fix-security-format.patch \ 14 file://fix-security-format.patch \
15 file://10-remove-build-date.patch \ 15 file://10-remove-build-date.patch \
16 file://zipnote-crashes-with-segfault.patch \ 16 file://zipnote-crashes-with-segfault.patch \
17 file://0001-configure-use-correct-CPP.patch \
18 file://0002-configure-support-PIC-code-build.patch \
17 " 19 "
18UPSTREAM_VERSION_UNKNOWN = "1" 20UPSTREAM_VERSION_UNKNOWN = "1"
19 21
diff --git a/meta/recipes-gnome/epiphany/epiphany_3.38.2.bb b/meta/recipes-gnome/epiphany/epiphany_3.38.2.bb
index 04f340f133..72d116da69 100644
--- a/meta/recipes-gnome/epiphany/epiphany_3.38.2.bb
+++ b/meta/recipes-gnome/epiphany/epiphany_3.38.2.bb
@@ -18,6 +18,7 @@ SRC_URI = "${GNOME_MIRROR}/${GNOMEBN}/${@gnome_verdir("${PV}")}/${GNOMEBN}-${PV}
18 file://0002-help-meson.build-disable-the-use-of-yelp.patch \ 18 file://0002-help-meson.build-disable-the-use-of-yelp.patch \
19 file://migrator.patch \ 19 file://migrator.patch \
20 file://distributor.patch \ 20 file://distributor.patch \
21 file://encode-untrusted-data.patch \
21 " 22 "
22SRC_URI[archive.sha256sum] = "8b05f2bcc1e80ecf4a10f6f01b3285087eb4cbdf5741dffb8c0355715ef5116d" 23SRC_URI[archive.sha256sum] = "8b05f2bcc1e80ecf4a10f6f01b3285087eb4cbdf5741dffb8c0355715ef5116d"
23 24
diff --git a/meta/recipes-gnome/epiphany/files/encode-untrusted-data.patch b/meta/recipes-gnome/epiphany/files/encode-untrusted-data.patch
new file mode 100644
index 0000000000..4805ee4e6b
--- /dev/null
+++ b/meta/recipes-gnome/epiphany/files/encode-untrusted-data.patch
@@ -0,0 +1,707 @@
1From: Michael Catanzaro <mcatanzaro@redhat.com>
2Subject: Properly encode untrusted data when injecting into trusted pages
3
4CVE: CVE-2021-45085 CVE-2021-45086 CVE-2021-45087 CVE-2021-45088
5
6Upstream-Status: Backport [https://gitlab.gnome.org/GNOME/epiphany/-/compare/c27a8180e12e6ec92292dcf53b9243815ad9aa2e...abac58c5191b7d653fbefa8d44e5c2bd4d002825?from_project_id=1906]
7
8Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
9Index: epiphany-browser/embed/ephy-about-handler.c
10===================================================================
11--- epiphany-browser.orig/embed/ephy-about-handler.c
12+++ epiphany-browser/embed/ephy-about-handler.c
13@@ -27,6 +27,7 @@
14 #include "ephy-file-helpers.h"
15 #include "ephy-flatpak-utils.h"
16 #include "ephy-history-service.h"
17+#include "ephy-output-encoding.h"
18 #include "ephy-prefs.h"
19 #include "ephy-settings.h"
20 #include "ephy-smaps.h"
21@@ -263,16 +264,34 @@ handle_applications_finished_cb (EphyAbo
22
23 for (p = applications; p; p = p->next) {
24 EphyWebApplication *app = (EphyWebApplication *)p->data;
25-
26+ g_autofree char *html_encoded_id = NULL;
27+ g_autofree char *encoded_icon_url = NULL;
28+ g_autofree char *encoded_name = NULL;
29+ g_autofree char *encoded_url = NULL;
30+ g_autofree char *js_encoded_id = NULL;
31+ g_autofree char *encoded_install_date = NULL;
32+
33+ /* Most of these fields are untrusted. The web app suggests its own title,
34+ * which gets used in the app ID and icon URL. The main URL could contain
35+ * anything. Install date is the only trusted field here in that it's
36+ * constructed by Epiphany, but it's a freeform string and we're encoding
37+ * everything else here anyway, so might as well encode this too.
38+ */
39+ html_encoded_id = ephy_encode_for_html_attribute (app->id);
40+ encoded_icon_url = ephy_encode_for_html_attribute (app->icon_url);
41+ encoded_name = ephy_encode_for_html_entity (app->name);
42+ encoded_url = ephy_encode_for_html_entity (app->url);
43+ js_encoded_id = ephy_encode_for_javascript (app->id);
44+ encoded_install_date = ephy_encode_for_html_entity (app->install_date);
45 g_string_append_printf (data_str,
46 "<tbody><tr id =\"%s\">"
47 "<td class=\"icon\"><img width=64 height=64 src=\"file://%s\"></img></td>"
48 "<td class=\"data\"><div class=\"appname\">%s</div><div class=\"appurl\">%s</div></td>"
49 "<td class=\"input\"><input type=\"button\" value=\"%s\" onclick=\"deleteWebApp('%s');\"></td>"
50 "<td class=\"date\">%s <br /> %s</td></tr></tbody>",
51- app->id, app->icon_url, app->name, app->url, _("Delete"), app->id,
52+ html_encoded_id, encoded_icon_url, encoded_name, encoded_url, _("Delete"), js_encoded_id,
53 /* Note for translators: this refers to the installation date. */
54- _("Installed on:"), app->install_date);
55+ _("Installed on:"), encoded_install_date);
56 }
57
58 g_string_append (data_str, "</table></div></body></html>");
59@@ -407,7 +426,9 @@ history_service_query_urls_cb (EphyHisto
60 EphyHistoryURL *url = (EphyHistoryURL *)l->data;
61 const char *snapshot;
62 g_autofree char *thumbnail_style = NULL;
63- g_autofree char *markup = NULL;
64+ g_autofree char *entity_encoded_title = NULL;
65+ g_autofree char *attribute_encoded_title = NULL;
66+ g_autofree char *encoded_url = NULL;
67
68 snapshot = ephy_snapshot_service_lookup_cached_snapshot_path (snapshot_service, url->url);
69 if (snapshot)
70@@ -415,15 +436,19 @@ history_service_query_urls_cb (EphyHisto
71 else
72 ephy_embed_shell_schedule_thumbnail_update (shell, url);
73
74- markup = g_markup_escape_text (url->title, -1);
75+ /* Title and URL are controlled by web content and could be malicious. */
76+ entity_encoded_title = ephy_encode_for_html_entity (url->title);
77+ attribute_encoded_title = ephy_encode_for_html_attribute (url->title);
78+ encoded_url = ephy_encode_for_html_attribute (url->url);
79 g_string_append_printf (data_str,
80 "<a class=\"overview-item\" title=\"%s\" href=\"%s\">"
81 " <div class=\"overview-close-button\" title=\"%s\"></div>"
82 " <span class=\"overview-thumbnail\"%s></span>"
83 " <span class=\"overview-title\">%s</span>"
84 "</a>",
85- markup, url->url, _("Remove from overview"),
86- thumbnail_style ? thumbnail_style : "", url->title);
87+ attribute_encoded_title, encoded_url, _("Remove from overview"),
88+ thumbnail_style ? thumbnail_style : "",
89+ entity_encoded_title);
90 }
91
92 data_str = g_string_append (data_str,
93Index: epiphany-browser/embed/ephy-pdf-handler.c
94===================================================================
95--- epiphany-browser.orig/embed/ephy-pdf-handler.c
96+++ epiphany-browser/embed/ephy-pdf-handler.c
97@@ -23,6 +23,7 @@
98
99 #include "ephy-embed-container.h"
100 #include "ephy-embed-shell.h"
101+#include "ephy-output-encoding.h"
102 #include "ephy-web-view.h"
103
104 #include <gio/gio.h>
105@@ -124,8 +125,9 @@ pdf_file_loaded (GObject *source,
106 GBytes *html_file;
107 g_autoptr (GError) error = NULL;
108 g_autoptr (GString) html = NULL;
109- g_autofree gchar *b64 = NULL;
110 g_autofree char *file_data = NULL;
111+ g_autofree char *encoded_file_data = NULL;
112+ g_autofree char *encoded_filename = NULL;
113 gsize len = 0;
114
115 if (!g_file_load_contents_finish (G_FILE (source), res, &file_data, &len, NULL, &error)) {
116@@ -134,13 +136,13 @@ pdf_file_loaded (GObject *source,
117 return;
118 }
119
120- html_file = g_resources_lookup_data ("/org/gnome/epiphany/pdfjs/web/viewer.html", 0, NULL);
121-
122- b64 = g_base64_encode ((const guchar *)file_data, len);
123 g_file_delete_async (G_FILE (source), G_PRIORITY_DEFAULT, NULL, pdf_file_deleted, NULL);
124
125- html = g_string_new ("");
126- g_string_printf (html, g_bytes_get_data (html_file, NULL), b64, self->file_name ? self->file_name : "");
127+ html = g_string_new (NULL);
128+ html_file = g_resources_lookup_data ("/org/gnome/epiphany/pdfjs/web/viewer.html", 0, NULL);
129+ encoded_file_data = g_base64_encode ((const guchar *)file_data, len);
130+ encoded_filename = self->file_name ? ephy_encode_for_html_attribute (self->file_name) : g_strdup ("");
131+ g_string_printf (html, g_bytes_get_data (html_file, NULL), encoded_file_data, encoded_filename);
132
133 finish_uri_scheme_request (self, g_strdup (html->str), NULL);
134 }
135Index: epiphany-browser/embed/ephy-reader-handler.c
136===================================================================
137--- epiphany-browser.orig/embed/ephy-reader-handler.c
138+++ epiphany-browser/embed/ephy-reader-handler.c
139@@ -24,6 +24,7 @@
140 #include "ephy-embed-container.h"
141 #include "ephy-embed-shell.h"
142 #include "ephy-lib-type-builtins.h"
143+#include "ephy-output-encoding.h"
144 #include "ephy-settings.h"
145 #include "ephy-web-view.h"
146
147@@ -156,7 +157,9 @@ readability_js_finish_cb (GObject *
148 g_autoptr (WebKitJavascriptResult) js_result = NULL;
149 g_autoptr (GError) error = NULL;
150 g_autofree gchar *byline = NULL;
151+ g_autofree gchar *encoded_byline = NULL;
152 g_autofree gchar *content = NULL;
153+ g_autofree gchar *encoded_title = NULL;
154 g_autoptr (GString) html = NULL;
155 g_autoptr (GBytes) style_css = NULL;
156 const gchar *title;
157@@ -173,10 +176,14 @@ readability_js_finish_cb (GObject *
158
159 byline = readability_get_property_string (js_result, "byline");
160 content = readability_get_property_string (js_result, "content");
161+ title = webkit_web_view_get_title (web_view);
162+
163+ encoded_byline = byline ? ephy_encode_for_html_entity (byline) : g_strdup ("");
164+ encoded_title = ephy_encode_for_html_entity (title);
165
166- html = g_string_new ("");
167+ html = g_string_new (NULL);
168 style_css = g_resources_lookup_data ("/org/gnome/epiphany/readability/reader.css", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
169- title = webkit_web_view_get_title (web_view);
170+
171 font_style = enum_nick (EPHY_TYPE_PREFS_READER_FONT_STYLE,
172 g_settings_get_enum (EPHY_SETTINGS_READER,
173 EPHY_PREFS_READER_FONT_STYLE));
174@@ -186,7 +193,8 @@ readability_js_finish_cb (GObject *
175
176 g_string_append_printf (html, "<style>%s</style>"
177 "<title>%s</title>"
178- "<meta http-equiv=\"Content-Type\" content=\"text/html;\" charset=\"UTF-8\">" \
179+ "<meta http-equiv='Content-Type' content='text/html;' charset='UTF-8'>" \
180+ "<meta http-equiv='Content-Security-Policy' content=\"script-src 'none'\">" \
181 "<body class='%s %s'>"
182 "<article>"
183 "<h2>"
184@@ -197,13 +205,27 @@ readability_js_finish_cb (GObject *
185 "</i>"
186 "<hr>",
187 (gchar *)g_bytes_get_data (style_css, NULL),
188- title,
189+ encoded_title,
190 font_style,
191 color_scheme,
192- title,
193- byline != NULL ? byline : "");
194+ encoded_title,
195+ encoded_byline);
196+
197+ /* We cannot encode the page content because it contains HTML tags inserted by
198+ * Readability.js. Upstream recommends that we use an XSS sanitizer like
199+ * DOMPurify plus Content-Security-Policy, but I'm not keen on adding more
200+ * bundled JS dependencies, and we have an advantage over Firefox in that we
201+ * don't need scripts to work at this point. So instead the above CSP
202+ * completely blocks all scripts, which should hopefully obviate the need for
203+ * a DOM purifier.
204+ *
205+ * Note the encoding for page title and byline is still required, as they're
206+ * not supposed to contain markup, and Readability.js unescapes them before
207+ * returning them to us.
208+ */
209 g_string_append (html, content);
210 g_string_append (html, "</article>");
211+ g_string_append (html, "</body>");
212
213 finish_uri_scheme_request (request, g_strdup (html->str), NULL);
214 }
215Index: epiphany-browser/embed/ephy-view-source-handler.c
216===================================================================
217--- epiphany-browser.orig/embed/ephy-view-source-handler.c
218+++ epiphany-browser/embed/ephy-view-source-handler.c
219@@ -23,6 +23,7 @@
220
221 #include "ephy-embed-container.h"
222 #include "ephy-embed-shell.h"
223+#include "ephy-output-encoding.h"
224 #include "ephy-web-view.h"
225
226 #include <gio/gio.h>
227@@ -109,7 +110,9 @@ web_resource_data_cb (WebKitWebResource
228 EphyViewSourceRequest *request)
229 {
230 g_autofree guchar *data = NULL;
231- g_autofree char *escaped_str = NULL;
232+ g_autofree char *data_str = NULL;
233+ g_autofree char *encoded_str = NULL;
234+ g_autofree char *encoded_uri = NULL;
235 g_autoptr (GError) error = NULL;
236 g_autofree char *html = NULL;
237 gsize length;
238@@ -120,8 +123,13 @@ web_resource_data_cb (WebKitWebResource
239 return;
240 }
241
242- /* Warning: data is not a string, so we pass length here because it's not NUL-terminated. */
243- escaped_str = g_markup_escape_text ((const char *)data, length);
244+ /* Convert data to a string */
245+ data_str = g_malloc (length + 1);
246+ memcpy (data_str, data, length);
247+ data_str[length] = '\0';
248+
249+ encoded_str = ephy_encode_for_html_entity (data_str);
250+ encoded_uri = ephy_encode_for_html_entity (webkit_web_resource_get_uri (resource));
251
252 html = g_strdup_printf ("<head>"
253 " <link rel='stylesheet' href='ephy-resource:///org/gnome/epiphany/highlightjs/nnfx.css' media='(prefers-color-scheme: no-preference), (prefers-color-scheme: light)'>"
254@@ -136,8 +144,8 @@ web_resource_data_cb (WebKitWebResource
255 " hljs.initLineNumbersOnLoad();</script>"
256 " <pre><code class='html'>%s</code></pre>"
257 "</body>",
258- webkit_web_resource_get_uri (resource),
259- escaped_str);
260+ encoded_uri,
261+ encoded_str);
262
263 finish_uri_scheme_request (request, g_steal_pointer (&html), NULL);
264 }
265Index: epiphany-browser/embed/ephy-web-view.c
266===================================================================
267--- epiphany-browser.orig/embed/ephy-web-view.c
268+++ epiphany-browser/embed/ephy-web-view.c
269@@ -38,6 +38,7 @@
270 #include "ephy-gsb-utils.h"
271 #include "ephy-history-service.h"
272 #include "ephy-lib-type-builtins.h"
273+#include "ephy-output-encoding.h"
274 #include "ephy-permissions-manager.h"
275 #include "ephy-prefs.h"
276 #include "ephy-reader-handler.h"
277@@ -1772,9 +1773,11 @@ format_network_error_page (const char *
278 const char **icon_name,
279 const char **style)
280 {
281- char *formatted_origin;
282- char *formatted_reason;
283- char *first_paragraph;
284+ g_autofree char *encoded_uri = NULL;
285+ g_autofree char *encoded_origin = NULL;
286+ g_autofree char *formatted_origin = NULL;
287+ g_autofree char *formatted_reason = NULL;
288+ g_autofree char *first_paragraph = NULL;
289 const char *second_paragraph;
290
291 /* Page title when a site cannot be loaded due to a network error. */
292@@ -1783,7 +1786,8 @@ format_network_error_page (const char *
293 /* Message title when a site cannot be loaded due to a network error. */
294 *message_title = g_strdup (_("Unable to display this website"));
295
296- formatted_origin = g_strdup_printf ("<strong>%s</strong>", origin);
297+ encoded_origin = ephy_encode_for_html_entity (origin);
298+ formatted_origin = g_strdup_printf ("<strong>%s</strong>", encoded_origin);
299 /* Error details when a site cannot be loaded due to a network error. */
300 first_paragraph = g_strdup_printf (_("The site at %s seems to be "
301 "unavailable."),
302@@ -1805,16 +1809,13 @@ format_network_error_page (const char *
303
304 /* The button on the network error page. DO NOT ADD MNEMONICS HERE. */
305 *button_label = g_strdup (_("Reload"));
306- *button_action = g_strdup_printf ("window.location = '%s';", uri);
307+ encoded_uri = ephy_encode_for_javascript (uri);
308+ *button_action = g_strdup_printf ("window.location = '%s';", encoded_uri);
309 /* Mnemonic for the Reload button on browser error pages. */
310 *button_accesskey = C_("reload-access-key", "R");
311
312 *icon_name = "network-error-symbolic.svg";
313 *style = "default";
314-
315- g_free (formatted_origin);
316- g_free (formatted_reason);
317- g_free (first_paragraph);
318 }
319
320 static void
321@@ -1828,10 +1829,12 @@ format_crash_error_page (const char *ur
322 const char **icon_name,
323 const char **style)
324 {
325- char *formatted_uri;
326- char *formatted_distributor;
327- char *first_paragraph;
328- char *second_paragraph;
329+ g_autofree char *html_encoded_uri = NULL;
330+ g_autofree char *js_encoded_uri = NULL;
331+ g_autofree char *formatted_uri = NULL;
332+ g_autofree char *formatted_distributor = NULL;
333+ g_autofree char *first_paragraph = NULL;
334+ g_autofree char *second_paragraph = NULL;
335
336 /* Page title when a site cannot be loaded due to a page crash error. */
337 *page_title = g_strdup_printf (_("Problem Loading Page"));
338@@ -1839,7 +1842,8 @@ format_crash_error_page (const char *ur
339 /* Message title when a site cannot be loaded due to a page crash error. */
340 *message_title = g_strdup (_("Oops! There may be a problem"));
341
342- formatted_uri = g_strdup_printf ("<strong>%s</strong>", uri);
343+ html_encoded_uri = ephy_encode_for_html_entity (uri);
344+ formatted_uri = g_strdup_printf ("<strong>%s</strong>", html_encoded_uri);
345 /* Error details when a site cannot be loaded due to a page crash error. */
346 first_paragraph = g_strdup_printf (_("The page %s may have caused Web to "
347 "close unexpectedly."),
348@@ -1858,17 +1862,13 @@ format_crash_error_page (const char *ur
349
350 /* The button on the page crash error page. DO NOT ADD MNEMONICS HERE. */
351 *button_label = g_strdup (_("Reload"));
352- *button_action = g_strdup_printf ("window.location = '%s';", uri);
353+ js_encoded_uri = ephy_encode_for_javascript (uri);
354+ *button_action = g_strdup_printf ("window.location = '%s';", js_encoded_uri);
355 /* Mnemonic for the Reload button on browser error pages. */
356 *button_accesskey = C_("reload-access-key", "R");
357
358 *icon_name = "computer-fail-symbolic.svg";
359 *style = "default";
360-
361- g_free (formatted_uri);
362- g_free (formatted_distributor);
363- g_free (first_paragraph);
364- g_free (second_paragraph);
365 }
366
367 static void
368@@ -1882,6 +1882,7 @@ format_process_crash_error_page (const c
369 const char **icon_name,
370 const char **style)
371 {
372+ g_autofree char *encoded_uri = NULL;
373 const char *first_paragraph;
374
375 /* Page title when a site cannot be loaded due to a process crash error. */
376@@ -1897,7 +1898,8 @@ format_process_crash_error_page (const c
377
378 /* The button on the process crash error page. DO NOT ADD MNEMONICS HERE. */
379 *button_label = g_strdup (_("Reload"));
380- *button_action = g_strdup_printf ("window.location = '%s';", uri);
381+ encoded_uri = ephy_encode_for_javascript (uri);
382+ *button_action = g_strdup_printf ("window.location = '%s';", encoded_uri);
383 /* Mnemonic for the Reload button on browser error pages. */
384 *button_accesskey = C_("reload-access-key", "R");
385
386@@ -1921,8 +1923,9 @@ format_tls_error_page (EphyWebView *vie
387 const char **icon_name,
388 const char **style)
389 {
390- char *formatted_origin;
391- char *first_paragraph;
392+ g_autofree char *encoded_origin = NULL;
393+ g_autofree char *formatted_origin = NULL;
394+ g_autofree char *first_paragraph = NULL;
395
396 /* Page title when a site is not loaded due to an invalid TLS certificate. */
397 *page_title = g_strdup_printf (_("Security Violation"));
398@@ -1930,7 +1933,8 @@ format_tls_error_page (EphyWebView *vie
399 /* Message title when a site is not loaded due to an invalid TLS certificate. */
400 *message_title = g_strdup (_("This Connection is Not Secure"));
401
402- formatted_origin = g_strdup_printf ("<strong>%s</strong>", origin);
403+ encoded_origin = ephy_encode_for_html_entity (origin);
404+ formatted_origin = g_strdup_printf ("<strong>%s</strong>", encoded_origin);
405 /* Error details when a site is not loaded due to an invalid TLS certificate. */
406 first_paragraph = g_strdup_printf (_("This does not look like the real %s. "
407 "Attackers might be trying to steal or "
408@@ -1956,9 +1960,6 @@ format_tls_error_page (EphyWebView *vie
409
410 *icon_name = "channel-insecure-symbolic.svg";
411 *style = "danger";
412-
413- g_free (formatted_origin);
414- g_free (first_paragraph);
415 }
416
417 static void
418@@ -1978,8 +1979,9 @@ format_unsafe_browsing_error_page (EphyW
419 const char **icon_name,
420 const char **style)
421 {
422- char *formatted_origin;
423- char *first_paragraph;
424+ g_autofree char *encoded_origin = NULL;
425+ g_autofree char *formatted_origin = NULL;
426+ g_autofree char *first_paragraph = NULL;
427
428 /* Page title when a site is flagged by Google Safe Browsing verification. */
429 *page_title = g_strdup_printf (_("Security Warning"));
430@@ -1987,7 +1989,8 @@ format_unsafe_browsing_error_page (EphyW
431 /* Message title on the unsafe browsing error page. */
432 *message_title = g_strdup (_("Unsafe website detected!"));
433
434- formatted_origin = g_strdup_printf ("<strong>%s</strong>", origin);
435+ encoded_origin = ephy_encode_for_html_entity (origin);
436+ formatted_origin = g_strdup_printf ("<strong>%s</strong>", encoded_origin);
437 /* Error details on the unsafe browsing error page.
438 * https://developers.google.com/safe-browsing/v4/usage-limits#UserWarnings
439 */
440@@ -2045,9 +2048,6 @@ format_unsafe_browsing_error_page (EphyW
441
442 *icon_name = "security-high-symbolic.svg";
443 *style = "danger";
444-
445- g_free (formatted_origin);
446- g_free (first_paragraph);
447 }
448
449 static void
450@@ -2061,7 +2061,8 @@ format_no_such_file_error_page (EphyWebV
451 const char **icon_name,
452 const char **style)
453 {
454- g_autofree gchar *formatted_origin = NULL;
455+ g_autofree gchar *encoded_address = NULL;
456+ g_autofree gchar *formatted_address = NULL;
457 g_autofree gchar *first_paragraph = NULL;
458 g_autofree gchar *second_paragraph = NULL;
459
460@@ -2071,10 +2072,11 @@ format_no_such_file_error_page (EphyWebV
461 /* Message title on the no such file error page. */
462 *message_title = g_strdup (_("File not found"));
463
464- formatted_origin = g_strdup_printf ("<strong>%s</strong>", view->address);
465+ encoded_address = ephy_encode_for_html_entity (view->address);
466+ formatted_address = g_strdup_printf ("<strong>%s</strong>", encoded_address);
467
468 first_paragraph = g_strdup_printf (_("%s could not be found."),
469- formatted_origin);
470+ formatted_address);
471 second_paragraph = g_strdup_printf (_("Please check the file name for "
472 "capitalization or other typing errors. Also check if "
473 "it has been moved, renamed, or deleted."));
474@@ -2109,19 +2111,19 @@ ephy_web_view_load_error_page (EphyWebVi
475 GError *error,
476 gpointer user_data)
477 {
478- GBytes *html_file;
479- GString *html = g_string_new ("");
480- char *origin = NULL;
481- char *lang = NULL;
482- char *page_title = NULL;
483- char *msg_title = NULL;
484- char *msg_body = NULL;
485- char *msg_details = NULL;
486- char *button_label = NULL;
487- char *hidden_button_label = NULL;
488- char *button_action = NULL;
489- char *hidden_button_action = NULL;
490- char *style_sheet = NULL;
491+ g_autoptr (GBytes) html_file = NULL;
492+ g_autoptr (GString) html = g_string_new (NULL);
493+ g_autofree char *origin = NULL;
494+ g_autofree char *lang = NULL;
495+ g_autofree char *page_title = NULL;
496+ g_autofree char *msg_title = NULL;
497+ g_autofree char *msg_body = NULL;
498+ g_autofree char *msg_details = NULL;
499+ g_autofree char *button_label = NULL;
500+ g_autofree char *hidden_button_label = NULL;
501+ g_autofree char *button_action = NULL;
502+ g_autofree char *hidden_button_action = NULL;
503+ g_autofree char *style_sheet = NULL;
504 const char *button_accesskey = NULL;
505 const char *hidden_button_accesskey = NULL;
506 const char *icon_name = NULL;
507@@ -2261,23 +2263,9 @@ ephy_web_view_load_error_page (EphyWebVi
508 button_accesskey, button_label);
509 #pragma GCC diagnostic pop
510
511- g_bytes_unref (html_file);
512- g_free (origin);
513- g_free (lang);
514- g_free (page_title);
515- g_free (msg_title);
516- g_free (msg_body);
517- g_free (msg_details);
518- g_free (button_label);
519- g_free (button_action);
520- g_free (hidden_button_label);
521- g_free (hidden_button_action);
522- g_free (style_sheet);
523-
524 /* Make our history backend ignore the next page load, since it will be an error page. */
525 ephy_web_view_freeze_history (view);
526 webkit_web_view_load_alternate_html (WEBKIT_WEB_VIEW (view), html->str, uri, 0);
527- g_string_free (html, TRUE);
528 }
529
530 static gboolean
531Index: epiphany-browser/lib/ephy-output-encoding.c
532===================================================================
533--- /dev/null
534+++ epiphany-browser/lib/ephy-output-encoding.c
535@@ -0,0 +1,117 @@
536+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
537+/*
538+ * Copyright © Red Hat Inc.
539+ *
540+ * This file is part of Epiphany.
541+ *
542+ * Epiphany is free software: you can redistribute it and/or modify
543+ * it under the terms of the GNU General Public License as published by
544+ * the Free Software Foundation, either version 3 of the License, or
545+ * (at your option) any later version.
546+ *
547+ * Epiphany is distributed in the hope that it will be useful,
548+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
549+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
550+ * GNU General Public License for more details.
551+ *
552+ * You should have received a copy of the GNU General Public License
553+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
554+ */
555+
556+#include "config.h"
557+#include "ephy-output-encoding.h"
558+
559+#include <glib.h>
560+
561+#if !GLIB_CHECK_VERSION(2, 68, 0)
562+static guint
563+g_string_replace (GString *string,
564+ const gchar *find,
565+ const gchar *replace,
566+ guint limit)
567+{
568+ gsize f_len, r_len, pos;
569+ gchar *cur, *next;
570+ guint n = 0;
571+
572+ g_return_val_if_fail (string != NULL, 0);
573+ g_return_val_if_fail (find != NULL, 0);
574+ g_return_val_if_fail (replace != NULL, 0);
575+
576+ f_len = strlen (find);
577+ r_len = strlen (replace);
578+ cur = string->str;
579+
580+ while ((next = strstr (cur, find)) != NULL)
581+ {
582+ pos = next - string->str;
583+ g_string_erase (string, pos, f_len);
584+ g_string_insert (string, pos, replace);
585+ cur = string->str + pos + r_len;
586+ n++;
587+ /* Only match the empty string once at any given position, to
588+ * avoid infinite loops */
589+ if (f_len == 0)
590+ {
591+ if (cur[0] == '\0')
592+ break;
593+ else
594+ cur++;
595+ }
596+ if (n == limit)
597+ break;
598+ }
599+
600+ return n;
601+}
602+#endif
603+
604+char *
605+ephy_encode_for_html_entity (const char *input)
606+{
607+ GString *str = g_string_new (input);
608+
609+ g_string_replace (str, "&", "&amp;", 0);
610+ g_string_replace (str, "<", "&lt;", 0);
611+ g_string_replace (str, ">", "&gt;", 0);
612+ g_string_replace (str, "\"", "&quot;", 0);
613+ g_string_replace (str, "'", "&#x27;", 0);
614+ g_string_replace (str, "/", "&#x2F;", 0);
615+
616+ return g_string_free (str, FALSE);
617+}
618+
619+static char *
620+encode_all_except_alnum (const char *input,
621+ const char *format)
622+{
623+ GString *str;
624+ const char *c = input;
625+
626+ if (!g_utf8_validate (input, -1, NULL))
627+ return g_strdup ("");
628+
629+ str = g_string_new (NULL);
630+ do {
631+ gunichar u = g_utf8_get_char (c);
632+ if (g_unichar_isalnum (u))
633+ g_string_append_unichar (str, u);
634+ else
635+ g_string_append_printf (str, format, u);
636+ c = g_utf8_next_char (c);
637+ } while (*c);
638+
639+ return g_string_free (str, FALSE);
640+}
641+
642+char *
643+ephy_encode_for_html_attribute (const char *input)
644+{
645+ return encode_all_except_alnum (input, "&#x%02x;");
646+}
647+
648+char *
649+ephy_encode_for_javascript (const char *input)
650+{
651+ return encode_all_except_alnum (input, "\\u%04u;");
652+}
653Index: epiphany-browser/lib/ephy-output-encoding.h
654===================================================================
655--- /dev/null
656+++ epiphany-browser/lib/ephy-output-encoding.h
657@@ -0,0 +1,38 @@
658+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
659+/*
660+ * Copyright © 2021 Red Hat Inc.
661+ *
662+ * This file is part of Epiphany.
663+ *
664+ * Epiphany is free software: you can redistribute it and/or modify
665+ * it under the terms of the GNU General Public License as published by
666+ * the Free Software Foundation, either version 3 of the License, or
667+ * (at your option) any later version.
668+ *
669+ * Epiphany is distributed in the hope that it will be useful,
670+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
671+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
672+ * GNU General Public License for more details.
673+ *
674+ * You should have received a copy of the GNU General Public License
675+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
676+ */
677+
678+#pragma once
679+
680+#include <glib.h>
681+
682+G_BEGIN_DECLS
683+
684+/* These functions implement the OWASP XSS prevention output encoding rules:
685+ * https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#output-encoding-rules-summary
686+ *
687+ * You must *carefully* read that document to safely inject untrusted data into
688+ * web content. Here be dragons.
689+ */
690+
691+char *ephy_encode_for_html_entity (const char *input);
692+char *ephy_encode_for_html_attribute (const char *input);
693+char *ephy_encode_for_javascript (const char *input);
694+
695+G_END_DECLS
696Index: epiphany-browser/lib/meson.build
697===================================================================
698--- epiphany-browser.orig/lib/meson.build
699+++ epiphany-browser/lib/meson.build
700@@ -21,6 +21,7 @@ libephymisc_sources = [
701 'ephy-langs.c',
702 'ephy-notification.c',
703 'ephy-notification-container.c',
704+ 'ephy-output-encoding.c',
705 'ephy-permissions-manager.c',
706 'ephy-profile-utils.c',
707 'ephy-search-engine-manager.c',
diff --git a/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0135.patch b/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0135.patch
new file mode 100644
index 0000000000..ae42dc8f6c
--- /dev/null
+++ b/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0135.patch
@@ -0,0 +1,117 @@
1From 63aee871365f9c9e7fa9125672302a0fb250d34d Mon Sep 17 00:00:00 2001
2From: Gert Wollny <gert.wollny@collabora.com>
3Date: Tue, 30 Nov 2021 09:16:24 +0100
4Subject: [PATCH 2/2] vrend: propperly check whether the shader image range is
5 correct
6
7Also add a test to check the integer underflow.
8
9Closes: #251
10Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
11Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
12
13cherry-pick from anongit.freedesktop.org/virglrenderer
14commit 2aed5d4...
15
16CVE: CVE-2022-0135
17Upstream-Status: Backport
18Signed-off-by: Joe Slater <joe.slater@windriver.com>
19
20---
21 src/vrend_decode.c | 3 +-
22 tests/test_fuzzer_formats.c | 57 +++++++++++++++++++++++++++++++++++++
23 2 files changed, 59 insertions(+), 1 deletion(-)
24
25diff --git a/src/vrend_decode.c b/src/vrend_decode.c
26index 91f5f24..6771b10 100644
27--- a/src/vrend_decode.c
28+++ b/src/vrend_decode.c
29@@ -1249,8 +1249,9 @@ static int vrend_decode_set_shader_images(struct vrend_context *ctx, const uint3
30 if (num_images < 1) {
31 return 0;
32 }
33+
34 if (start_slot > PIPE_MAX_SHADER_IMAGES ||
35- start_slot > PIPE_MAX_SHADER_IMAGES - num_images)
36+ start_slot + num_images > PIPE_MAX_SHADER_IMAGES)
37 return EINVAL;
38
39 for (uint32_t i = 0; i < num_images; i++) {
40diff --git a/tests/test_fuzzer_formats.c b/tests/test_fuzzer_formats.c
41index 154a2e5..e32caf0 100644
42--- a/tests/test_fuzzer_formats.c
43+++ b/tests/test_fuzzer_formats.c
44@@ -958,6 +958,61 @@ static void test_vrend_set_signle_abo_heap_overflow() {
45 virgl_renderer_submit_cmd((void *) cmd, ctx_id, 0xde);
46 }
47
48+static void test_vrend_set_shader_images_overflow()
49+{
50+ uint32_t num_shaders = PIPE_MAX_SHADER_IMAGES + 1;
51+ uint32_t size = num_shaders * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 3;
52+ uint32_t cmd[size];
53+ int i = 0;
54+ cmd[i++] = ((size - 1)<< 16) | 0 << 8 | VIRGL_CCMD_SET_SHADER_IMAGES;
55+ cmd[i++] = PIPE_SHADER_FRAGMENT;
56+ memset(&cmd[i], 0, size - i);
57+
58+ virgl_renderer_submit_cmd((void *) cmd, ctx_id, size);
59+}
60+
61+/* Test adapted from yaojun8558363@gmail.com:
62+ * https://gitlab.freedesktop.org/virgl/virglrenderer/-/issues/250
63+*/
64+static void test_vrend_3d_resource_overflow() {
65+
66+ struct virgl_renderer_resource_create_args resource;
67+ resource.handle = 0x4c474572;
68+ resource.target = PIPE_TEXTURE_2D_ARRAY;
69+ resource.format = VIRGL_FORMAT_Z24X8_UNORM;
70+ resource.nr_samples = 2;
71+ resource.last_level = 0;
72+ resource.array_size = 3;
73+ resource.bind = VIRGL_BIND_SAMPLER_VIEW;
74+ resource.depth = 1;
75+ resource.width = 8;
76+ resource.height = 4;
77+ resource.flags = 0;
78+
79+ virgl_renderer_resource_create(&resource, NULL, 0);
80+ virgl_renderer_ctx_attach_resource(ctx_id, resource.handle);
81+
82+ uint32_t size = 0x400;
83+ uint32_t cmd[size];
84+ int i = 0;
85+ cmd[i++] = (size - 1) << 16 | 0 << 8 | VIRGL_CCMD_RESOURCE_INLINE_WRITE;
86+ cmd[i++] = resource.handle;
87+ cmd[i++] = 0; // level
88+ cmd[i++] = 0; // usage
89+ cmd[i++] = 0; // stride
90+ cmd[i++] = 0; // layer_stride
91+ cmd[i++] = 0; // x
92+ cmd[i++] = 0; // y
93+ cmd[i++] = 0; // z
94+ cmd[i++] = 8; // w
95+ cmd[i++] = 4; // h
96+ cmd[i++] = 3; // d
97+ memset(&cmd[i], 0, size - i);
98+
99+ virgl_renderer_submit_cmd((void *) cmd, ctx_id, size);
100+}
101+
102+
103 int main()
104 {
105 initialize_environment();
106@@ -980,6 +1035,8 @@ int main()
107 test_cs_nullpointer_deference();
108 test_vrend_set_signle_abo_heap_overflow();
109
110+ test_vrend_set_shader_images_overflow();
111+ test_vrend_3d_resource_overflow();
112
113 virgl_renderer_context_destroy(ctx_id);
114 virgl_renderer_cleanup(&cookie);
115--
1162.25.1
117
diff --git a/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0175.patch b/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0175.patch
new file mode 100644
index 0000000000..8bbb9eb579
--- /dev/null
+++ b/meta/recipes-graphics/virglrenderer/virglrenderer/cve-2022-0175.patch
@@ -0,0 +1,112 @@
1From 5ca7aca001092c557f0b6fc1ba3db7dcdab860b7 Mon Sep 17 00:00:00 2001
2From: Gert Wollny <gert.wollny@collabora.com>
3Date: Tue, 30 Nov 2021 09:29:42 +0100
4Subject: [PATCH 1/2] vrend: clear memory when allocating a host-backed memory
5 resource
6
7Closes: #249
8Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
9Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
10
11cherry-pick from anongit.freedesktop.org/virglrenderer
12commit b05bb61...
13
14CVE: CVE-2022-0175
15Upstream-Status: Backport
16Signed-off-by: Joe Slater <joe.slater@windriver.com>
17
18Patch to vrend_renderer.c modified to apply to version used by hardknott.
19Patch to test_virgl_transfer.c unchanged.
20
21Signed-off-by: Joe Slater <joe.slater@windriver.com>
22
23---
24 src/vrend_renderer.c | 2 +-
25 tests/test_virgl_transfer.c | 51 +++++++++++++++++++++++++++++++++++++
26 2 files changed, 52 insertions(+), 1 deletion(-)
27
28diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
29index ad7a351..d84f785 100644
30--- a/src/vrend_renderer.c
31+++ b/src/vrend_renderer.c
32@@ -6646,7 +6646,7 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a
33 if (args->bind == VIRGL_BIND_CUSTOM) {
34 /* use iovec directly when attached */
35 gr->storage_bits |= VREND_STORAGE_HOST_SYSTEM_MEMORY;
36- gr->ptr = malloc(args->width);
37+ gr->ptr = calloc(1, args->width);
38 if (!gr->ptr) {
39 FREE(gr);
40 return ENOMEM;
41diff --git a/tests/test_virgl_transfer.c b/tests/test_virgl_transfer.c
42index 2c8669a..8f8e98a 100644
43--- a/tests/test_virgl_transfer.c
44+++ b/tests/test_virgl_transfer.c
45@@ -952,6 +952,56 @@ START_TEST(virgl_test_transfer_near_res_bounds_with_stride_succeeds)
46 }
47 END_TEST
48
49+START_TEST(test_vrend_host_backed_memory_no_data_leak)
50+{
51+ struct iovec iovs[1];
52+ int niovs = 1;
53+
54+ struct virgl_context ctx = {0};
55+
56+ int ret = testvirgl_init_ctx_cmdbuf(&ctx);
57+
58+ struct virgl_renderer_resource_create_args res;
59+ res.handle = 0x400;
60+ res.target = PIPE_BUFFER;
61+ res.format = VIRGL_FORMAT_R8_UNORM;
62+ res.nr_samples = 0;
63+ res.last_level = 0;
64+ res.array_size = 1;
65+ res.bind = VIRGL_BIND_CUSTOM;
66+ res.depth = 1;
67+ res.width = 32;
68+ res.height = 1;
69+ res.flags = 0;
70+
71+ uint32_t size = 32;
72+ uint8_t* data = calloc(1, size);
73+ memset(data, 1, 32);
74+ iovs[0].iov_base = data;
75+ iovs[0].iov_len = size;
76+
77+ struct pipe_box box = {0,0,0, size, 1,1};
78+
79+ virgl_renderer_resource_create(&res, NULL, 0);
80+ virgl_renderer_ctx_attach_resource(ctx.ctx_id, res.handle);
81+
82+ ret = virgl_renderer_transfer_read_iov(res.handle, ctx.ctx_id, 0, 0, 0,
83+ (struct virgl_box *)&box, 0, iovs, niovs);
84+
85+ ck_assert_int_eq(ret, 0);
86+
87+ for (int i = 0; i < 32; ++i)
88+ ck_assert_int_eq(data[i], 0);
89+
90+ virgl_renderer_ctx_detach_resource(1, res.handle);
91+
92+ virgl_renderer_resource_unref(res.handle);
93+ free(data);
94+
95+}
96+END_TEST
97+
98+
99 static Suite *virgl_init_suite(void)
100 {
101 Suite *s;
102@@ -981,6 +1031,7 @@ static Suite *virgl_init_suite(void)
103 tcase_add_test(tc_core, virgl_test_transfer_buffer_bad_strides);
104 tcase_add_test(tc_core, virgl_test_transfer_2d_array_bad_layer_stride);
105 tcase_add_test(tc_core, virgl_test_transfer_2d_bad_level);
106+ tcase_add_test(tc_core, test_vrend_host_backed_memory_no_data_leak);
107
108 tcase_add_loop_test(tc_core, virgl_test_transfer_res_read_valid, 0, PIPE_MAX_TEXTURE_TYPES);
109 tcase_add_loop_test(tc_core, virgl_test_transfer_res_write_valid, 0, PIPE_MAX_TEXTURE_TYPES);
110--
1112.31.1
112
diff --git a/meta/recipes-graphics/virglrenderer/virglrenderer_0.8.2.bb b/meta/recipes-graphics/virglrenderer/virglrenderer_0.8.2.bb
index 7f035f820a..1c32a573b2 100644
--- a/meta/recipes-graphics/virglrenderer/virglrenderer_0.8.2.bb
+++ b/meta/recipes-graphics/virglrenderer/virglrenderer_0.8.2.bb
@@ -10,9 +10,11 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=c81c08eeefd9418fca8f88309a76db10"
10 10
11DEPENDS = "libdrm virtual/libgl libepoxy" 11DEPENDS = "libdrm virtual/libgl libepoxy"
12SRCREV = "7d204f3927be65fb3365dce01dbcd04d447a4985" 12SRCREV = "7d204f3927be65fb3365dce01dbcd04d447a4985"
13SRC_URI = "git://anongit.freedesktop.org/virglrenderer;branch=master \ 13SRC_URI = "git://anongit.freedesktop.org/git/virglrenderer;branch=master \
14 file://0001-gallium-Expand-libc-check-to-be-platform-OS-check.patch \ 14 file://0001-gallium-Expand-libc-check-to-be-platform-OS-check.patch \
15 file://0001-meson.build-use-python3-directly-for-python.patch \ 15 file://0001-meson.build-use-python3-directly-for-python.patch \
16 file://cve-2022-0135.patch \
17 file://cve-2022-0175.patch \
16 " 18 "
17 19
18S = "${WORKDIR}/git" 20S = "${WORKDIR}/git"
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg.inc b/meta/recipes-graphics/xorg-xserver/xserver-xorg.inc
index b3e03744c0..d83cb94317 100644
--- a/meta/recipes-graphics/xorg-xserver/xserver-xorg.inc
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg.inc
@@ -17,7 +17,15 @@ PE = "2"
17XORG_PN = "xorg-server" 17XORG_PN = "xorg-server"
18SRC_URI = "${XORG_MIRROR}/individual/xserver/${XORG_PN}-${PV}.tar.bz2" 18SRC_URI = "${XORG_MIRROR}/individual/xserver/${XORG_PN}-${PV}.tar.bz2"
19 19
20CVE_PRODUCT = "xorg-server" 20CVE_PRODUCT = "xorg-server x_server"
21# This is specific to Debian's xserver-wrapper.c
22CVE_CHECK_WHITELIST += "CVE-2011-4613"
23# As per upstream, exploiting this flaw is non-trivial and it requires exact
24# timing on the behalf of the attacker. Many graphical applications exit if their
25# connection to the X server is lost, so a typical desktop session is either
26# impossible or difficult to exploit. There is currently no upstream patch
27# available for this flaw.
28CVE_CHECK_WHITELIST += "CVE-2020-25697"
21 29
22S = "${WORKDIR}/${XORG_PN}-${PV}" 30S = "${WORKDIR}/${XORG_PN}-${PV}"
23 31
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4008.patch b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4008.patch
new file mode 100644
index 0000000000..3277be0185
--- /dev/null
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4008.patch
@@ -0,0 +1,59 @@
1Backport patch to fix CVE-2021-4008.
2
3CVE: CVE-2021-4008
4Upstream-Status: Backport [https://gitlab.freedesktop.org/xorg/xserver/-/commit/ebce7e2]
5
6Signed-off-by: Kai Kang <kai.kang@windriver.com>
7
8From ebce7e2d80e7c80e1dda60f2f0bc886f1106ba60 Mon Sep 17 00:00:00 2001
9From: Povilas Kanapickas <povilas@radix.lt>
10Date: Tue, 14 Dec 2021 15:00:03 +0200
11Subject: [PATCH] render: Fix out of bounds access in
12 SProcRenderCompositeGlyphs()
13
14ZDI-CAN-14192, CVE-2021-4008
15
16This vulnerability was discovered and the fix was suggested by:
17Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
18
19Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
20---
21 render/render.c | 9 +++++++++
22 1 file changed, 9 insertions(+)
23
24diff --git a/render/render.c b/render/render.c
25index c376090ca..456f156d4 100644
26--- a/render/render.c
27+++ b/render/render.c
28@@ -2309,6 +2309,9 @@ SProcRenderCompositeGlyphs(ClientPtr client)
29
30 i = elt->len;
31 if (i == 0xff) {
32+ if (buffer + 4 > end) {
33+ return BadLength;
34+ }
35 swapl((int *) buffer);
36 buffer += 4;
37 }
38@@ -2319,12 +2322,18 @@ SProcRenderCompositeGlyphs(ClientPtr client)
39 buffer += i;
40 break;
41 case 2:
42+ if (buffer + i * 2 > end) {
43+ return BadLength;
44+ }
45 while (i--) {
46 swaps((short *) buffer);
47 buffer += 2;
48 }
49 break;
50 case 4:
51+ if (buffer + i * 4 > end) {
52+ return BadLength;
53+ }
54 while (i--) {
55 swapl((int *) buffer);
56 buffer += 4;
57--
58GitLab
59
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4009.patch b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4009.patch
new file mode 100644
index 0000000000..ddfbb43ee4
--- /dev/null
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4009.patch
@@ -0,0 +1,50 @@
1Backport patch to fix CVE-2021-4009.
2
3CVE: CVE-2021-4009
4Upstream-Status: Backport [https://gitlab.freedesktop.org/xorg/xserver/-/commit/b519675]
5
6Signed-off-by: Kai Kang <kai.kang@windriver.com>
7
8From b5196750099ae6ae582e1f46bd0a6dad29550e02 Mon Sep 17 00:00:00 2001
9From: Povilas Kanapickas <povilas@radix.lt>
10Date: Tue, 14 Dec 2021 15:00:01 +0200
11Subject: [PATCH] xfixes: Fix out of bounds access in
12 *ProcXFixesCreatePointerBarrier()
13
14ZDI-CAN-14950, CVE-2021-4009
15
16This vulnerability was discovered and the fix was suggested by:
17Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
18
19Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
20---
21 xfixes/cursor.c | 6 ++++--
22 1 file changed, 4 insertions(+), 2 deletions(-)
23
24diff --git a/xfixes/cursor.c b/xfixes/cursor.c
25index 60580b88f..c5d4554b2 100644
26--- a/xfixes/cursor.c
27+++ b/xfixes/cursor.c
28@@ -1010,7 +1010,8 @@ ProcXFixesCreatePointerBarrier(ClientPtr client)
29 {
30 REQUEST(xXFixesCreatePointerBarrierReq);
31
32- REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
33+ REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
34+ pad_to_int32(stuff->num_devices * sizeof(CARD16)));
35 LEGAL_NEW_RESOURCE(stuff->barrier, client);
36
37 return XICreatePointerBarrier(client, stuff);
38@@ -1027,7 +1028,8 @@ SProcXFixesCreatePointerBarrier(ClientPtr client)
39
40 swaps(&stuff->length);
41 swaps(&stuff->num_devices);
42- REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq, pad_to_int32(stuff->num_devices));
43+ REQUEST_FIXED_SIZE(xXFixesCreatePointerBarrierReq,
44+ pad_to_int32(stuff->num_devices * sizeof(CARD16)));
45
46 swapl(&stuff->barrier);
47 swapl(&stuff->window);
48--
49GitLab
50
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4010.patch b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4010.patch
new file mode 100644
index 0000000000..06ebe7d077
--- /dev/null
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4010.patch
@@ -0,0 +1,39 @@
1Backport patch to fix CVE-2021-4010.
2
3CVE: CVE-2021-4010
4Upstream-Status: Backport [https://gitlab.freedesktop.org/xorg/xserver/-/commit/6c4c530]
5
6Signed-off-by: Kai Kang <kai.kang@windriver.com>
7
8From 6c4c53010772e3cb4cb8acd54950c8eec9c00d21 Mon Sep 17 00:00:00 2001
9From: Povilas Kanapickas <povilas@radix.lt>
10Date: Tue, 14 Dec 2021 15:00:02 +0200
11Subject: [PATCH] Xext: Fix out of bounds access in SProcScreenSaverSuspend()
12
13ZDI-CAN-14951, CVE-2021-4010
14
15This vulnerability was discovered and the fix was suggested by:
16Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
17
18Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
19---
20 Xext/saver.c | 2 +-
21 1 file changed, 1 insertion(+), 1 deletion(-)
22
23diff --git a/Xext/saver.c b/Xext/saver.c
24index 1d7e3cadf..f813ba08d 100644
25--- a/Xext/saver.c
26+++ b/Xext/saver.c
27@@ -1351,8 +1351,8 @@ SProcScreenSaverSuspend(ClientPtr client)
28 REQUEST(xScreenSaverSuspendReq);
29
30 swaps(&stuff->length);
31- swapl(&stuff->suspend);
32 REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
33+ swapl(&stuff->suspend);
34 return ProcScreenSaverSuspend(client);
35 }
36
37--
38GitLab
39
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4011.patch b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4011.patch
new file mode 100644
index 0000000000..c7eb03091d
--- /dev/null
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg/CVE-2021-4011.patch
@@ -0,0 +1,40 @@
1Backport patch to fix CVE-2021-4011.
2
3CVE: CVE-2021-4011
4Upstream-Status: Backport [https://gitlab.freedesktop.org/xorg/xserver/-/commit/e56f61c]
5
6Signed-off-by: Kai Kang <kai.kang@windriver.com>
7
8From e56f61c79fc3cee26d83cda0f84ae56d5979f768 Mon Sep 17 00:00:00 2001
9From: Povilas Kanapickas <povilas@radix.lt>
10Date: Tue, 14 Dec 2021 15:00:00 +0200
11Subject: [PATCH] record: Fix out of bounds access in SwapCreateRegister()
12
13ZDI-CAN-14952, CVE-2021-4011
14
15This vulnerability was discovered and the fix was suggested by:
16Jan-Niklas Sohn working with Trend Micro Zero Day Initiative
17
18Signed-off-by: Povilas Kanapickas <povilas@radix.lt>
19---
20 record/record.c | 4 ++--
21 1 file changed, 2 insertions(+), 2 deletions(-)
22
23diff --git a/record/record.c b/record/record.c
24index be154525d..e123867a7 100644
25--- a/record/record.c
26+++ b/record/record.c
27@@ -2516,8 +2516,8 @@ SwapCreateRegister(ClientPtr client, xRecordRegisterClientsReq * stuff)
28 swapl(pClientID);
29 }
30 if (stuff->nRanges >
31- client->req_len - bytes_to_int32(sz_xRecordRegisterClientsReq)
32- - stuff->nClients)
33+ (client->req_len - bytes_to_int32(sz_xRecordRegisterClientsReq)
34+ - stuff->nClients) / bytes_to_int32(sz_xRecordRange))
35 return BadLength;
36 RecordSwapRanges((xRecordRange *) pClientID, stuff->nRanges);
37 return Success;
38--
39GitLab
40
diff --git a/meta/recipes-graphics/xorg-xserver/xserver-xorg_1.20.10.bb b/meta/recipes-graphics/xorg-xserver/xserver-xorg_1.20.10.bb
index e0551fa999..58f1eb328e 100644
--- a/meta/recipes-graphics/xorg-xserver/xserver-xorg_1.20.10.bb
+++ b/meta/recipes-graphics/xorg-xserver/xserver-xorg_1.20.10.bb
@@ -9,6 +9,10 @@ SRC_URI += "file://0001-xf86pciBus.c-use-Intel-ddx-only-for-pre-gen4-hardwar.pat
9 file://0001-Fix-segfault-on-probing-a-non-PCI-platform-device-on.patch \ 9 file://0001-Fix-segfault-on-probing-a-non-PCI-platform-device-on.patch \
10 file://CVE-2021-3472.patch \ 10 file://CVE-2021-3472.patch \
11 file://0001-hw-xwayland-Makefile.am-fix-build-without-glx.patch \ 11 file://0001-hw-xwayland-Makefile.am-fix-build-without-glx.patch \
12 file://CVE-2021-4008.patch \
13 file://CVE-2021-4009.patch \
14 file://CVE-2021-4010.patch \
15 file://CVE-2021-4011.patch \
12 " 16 "
13SRC_URI[sha256sum] = "977420c082450dc808de301ef56af4856d653eea71519a973c3490a780cb7c99" 17SRC_URI[sha256sum] = "977420c082450dc808de301ef56af4856d653eea71519a973c3490a780cb7c99"
14 18
diff --git a/meta/recipes-kernel/linux-firmware/linux-firmware_20211027.bb b/meta/recipes-kernel/linux-firmware/linux-firmware_20220310.bb
index 76aed9d443..7a6cb1903b 100644
--- a/meta/recipes-kernel/linux-firmware/linux-firmware_20211027.bb
+++ b/meta/recipes-kernel/linux-firmware/linux-firmware_20220310.bb
@@ -72,7 +72,7 @@ LICENSE = "\
72LIC_FILES_CHKSUM = "file://LICENCE.Abilis;md5=b5ee3f410780e56711ad48eadc22b8bc \ 72LIC_FILES_CHKSUM = "file://LICENCE.Abilis;md5=b5ee3f410780e56711ad48eadc22b8bc \
73 file://LICENCE.adsp_sst;md5=615c45b91a5a4a9fe046d6ab9a2df728 \ 73 file://LICENCE.adsp_sst;md5=615c45b91a5a4a9fe046d6ab9a2df728 \
74 file://LICENCE.agere;md5=af0133de6b4a9b2522defd5f188afd31 \ 74 file://LICENCE.agere;md5=af0133de6b4a9b2522defd5f188afd31 \
75 file://LICENSE.amdgpu;md5=d357524f5099e2a3db3c1838921c593f \ 75 file://LICENSE.amdgpu;md5=44c1166d052226cb2d6c8d7400090203 \
76 file://LICENSE.amd-ucode;md5=3c5399dc9148d7f0e1f41e34b69cf14f \ 76 file://LICENSE.amd-ucode;md5=3c5399dc9148d7f0e1f41e34b69cf14f \
77 file://LICENSE.amlogic_vdec;md5=dc44f59bf64a81643e500ad3f39a468a \ 77 file://LICENSE.amlogic_vdec;md5=dc44f59bf64a81643e500ad3f39a468a \
78 file://LICENCE.atheros_firmware;md5=30a14c7823beedac9fa39c64fdd01a13 \ 78 file://LICENCE.atheros_firmware;md5=30a14c7823beedac9fa39c64fdd01a13 \
@@ -132,7 +132,7 @@ LIC_FILES_CHKSUM = "file://LICENCE.Abilis;md5=b5ee3f410780e56711ad48eadc22b8bc \
132 file://LICENCE.xc4000;md5=0ff51d2dc49fce04814c9155081092f0 \ 132 file://LICENCE.xc4000;md5=0ff51d2dc49fce04814c9155081092f0 \
133 file://LICENCE.xc5000;md5=1e170c13175323c32c7f4d0998d53f66 \ 133 file://LICENCE.xc5000;md5=1e170c13175323c32c7f4d0998d53f66 \
134 file://LICENCE.xc5000c;md5=12b02efa3049db65d524aeb418dd87ca \ 134 file://LICENCE.xc5000c;md5=12b02efa3049db65d524aeb418dd87ca \
135 file://WHENCE;md5=d627873bd934d7c52b2c8191304a8eb7 \ 135 file://WHENCE;md5=45a9c4a92d152e9495db81e1192f2bdc \
136 " 136 "
137 137
138# These are not common licenses, set NO_GENERIC_LICENSE for them 138# These are not common licenses, set NO_GENERIC_LICENSE for them
@@ -205,7 +205,7 @@ PE = "1"
205 205
206SRC_URI = "${KERNELORG_MIRROR}/linux/kernel/firmware/${BPN}-${PV}.tar.xz" 206SRC_URI = "${KERNELORG_MIRROR}/linux/kernel/firmware/${BPN}-${PV}.tar.xz"
207 207
208SRC_URI[sha256sum] = "bc2657dd8eb82386a9a7ec6df9ccf31c32c7e9073c05d37786c1edc273f9440a" 208SRC_URI[sha256sum] = "5938ee717b2023b48f6bfcf344b40ddc947e3e22c0bc36d4c3418f90fea68182"
209 209
210inherit allarch 210inherit allarch
211 211
@@ -751,6 +751,7 @@ FILES_${PN}-bcm4356-pcie = "${nonarch_base_libdir}/firmware/brcm/brcmfmac4356-pc
751FILES_${PN}-bcm4373 = "${nonarch_base_libdir}/firmware/brcm/brcmfmac4373-sdio.bin \ 751FILES_${PN}-bcm4373 = "${nonarch_base_libdir}/firmware/brcm/brcmfmac4373-sdio.bin \
752 ${nonarch_base_libdir}/firmware/brcm/brcmfmac4373.bin \ 752 ${nonarch_base_libdir}/firmware/brcm/brcmfmac4373.bin \
753 ${nonarch_base_libdir}/firmware/cypress/cyfmac4373-sdio.bin \ 753 ${nonarch_base_libdir}/firmware/cypress/cyfmac4373-sdio.bin \
754 ${nonarch_base_libdir}/firmware/brcm/brcmfmac4373-sdio.clm_blob \
754" 755"
755 756
756LICENSE_${PN}-bcm-0bb4-0306 = "Firmware-cypress" 757LICENSE_${PN}-bcm-0bb4-0306 = "Firmware-cypress"
diff --git a/meta/recipes-kernel/linux/linux-yocto-rt_5.10.bb b/meta/recipes-kernel/linux/linux-yocto-rt_5.10.bb
index 93ebccff3d..50e6a9f1e2 100644
--- a/meta/recipes-kernel/linux/linux-yocto-rt_5.10.bb
+++ b/meta/recipes-kernel/linux/linux-yocto-rt_5.10.bb
@@ -11,13 +11,13 @@ python () {
11 raise bb.parse.SkipRecipe("Set PREFERRED_PROVIDER_virtual/kernel to linux-yocto-rt to enable it") 11 raise bb.parse.SkipRecipe("Set PREFERRED_PROVIDER_virtual/kernel to linux-yocto-rt to enable it")
12} 12}
13 13
14SRCREV_machine ?= "12f6a7187b3c8abab5e139dbfdf7f58f265f4169" 14SRCREV_machine ?= "7f96d3fd60eea0ab38afdf07b3fc7c8c9f501802"
15SRCREV_meta ?= "a0238f7f4f2222d08bb18147bb5e24cc877b0546" 15SRCREV_meta ?= "24ab54209a8822aad92afe2c51ea5b95f5175394"
16 16
17SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;branch=${KBRANCH};name=machine \ 17SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;branch=${KBRANCH};name=machine \
18 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.10;destsuffix=${KMETA}" 18 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.10;destsuffix=${KMETA}"
19 19
20LINUX_VERSION ?= "5.10.78" 20LINUX_VERSION ?= "5.10.107"
21 21
22LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" 22LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
23 23
diff --git a/meta/recipes-kernel/linux/linux-yocto-rt_5.4.bb b/meta/recipes-kernel/linux/linux-yocto-rt_5.4.bb
index e560c408cc..2134f848b2 100644
--- a/meta/recipes-kernel/linux/linux-yocto-rt_5.4.bb
+++ b/meta/recipes-kernel/linux/linux-yocto-rt_5.4.bb
@@ -11,13 +11,13 @@ python () {
11 raise bb.parse.SkipRecipe("Set PREFERRED_PROVIDER_virtual/kernel to linux-yocto-rt to enable it") 11 raise bb.parse.SkipRecipe("Set PREFERRED_PROVIDER_virtual/kernel to linux-yocto-rt to enable it")
12} 12}
13 13
14SRCREV_machine ?= "88b78bac3bf83e6b3ef08d77f895bba5128cc1cd" 14SRCREV_machine ?= "40423bc7ab2cc609f955a3dc16a0d854c1504ce3"
15SRCREV_meta ?= "9e3ab4e615b651c1b63d4f0cce71da79a3e89763" 15SRCREV_meta ?= "e8c675c7e11fbd96cd812dfb9f4f6fb6f92b6abb"
16 16
17SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;branch=${KBRANCH};name=machine \ 17SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;branch=${KBRANCH};name=machine \
18 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.4;destsuffix=${KMETA}" 18 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.4;destsuffix=${KMETA}"
19 19
20LINUX_VERSION ?= "5.4.153" 20LINUX_VERSION ?= "5.4.178"
21 21
22LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" 22LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
23 23
diff --git a/meta/recipes-kernel/linux/linux-yocto-tiny_5.10.bb b/meta/recipes-kernel/linux/linux-yocto-tiny_5.10.bb
index d3402f3a25..8f22c89165 100644
--- a/meta/recipes-kernel/linux/linux-yocto-tiny_5.10.bb
+++ b/meta/recipes-kernel/linux/linux-yocto-tiny_5.10.bb
@@ -6,7 +6,7 @@ KCONFIG_MODE = "--allnoconfig"
6 6
7require recipes-kernel/linux/linux-yocto.inc 7require recipes-kernel/linux/linux-yocto.inc
8 8
9LINUX_VERSION ?= "5.10.78" 9LINUX_VERSION ?= "5.10.107"
10LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" 10LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
11 11
12DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}" 12DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}"
@@ -15,9 +15,9 @@ DEPENDS += "openssl-native util-linux-native"
15KMETA = "kernel-meta" 15KMETA = "kernel-meta"
16KCONF_BSP_AUDIT_LEVEL = "2" 16KCONF_BSP_AUDIT_LEVEL = "2"
17 17
18SRCREV_machine_qemuarm ?= "cdec5045c5323846adaf2510e539843d0cfe74ae" 18SRCREV_machine_qemuarm ?= "d47f1b40f2f77d0c810defd853c69eb39cb84bf5"
19SRCREV_machine ?= "344c0c38f5b892312b0a1db7f613d2704dd4942f" 19SRCREV_machine ?= "1ae0844c6a36151066744e43fd30db3a946bc21d"
20SRCREV_meta ?= "a0238f7f4f2222d08bb18147bb5e24cc877b0546" 20SRCREV_meta ?= "24ab54209a8822aad92afe2c51ea5b95f5175394"
21 21
22PV = "${LINUX_VERSION}+git${SRCPV}" 22PV = "${LINUX_VERSION}+git${SRCPV}"
23 23
diff --git a/meta/recipes-kernel/linux/linux-yocto-tiny_5.4.bb b/meta/recipes-kernel/linux/linux-yocto-tiny_5.4.bb
index e6e0ee73b2..35177d4f6c 100644
--- a/meta/recipes-kernel/linux/linux-yocto-tiny_5.4.bb
+++ b/meta/recipes-kernel/linux/linux-yocto-tiny_5.4.bb
@@ -6,7 +6,7 @@ KCONFIG_MODE = "--allnoconfig"
6 6
7require recipes-kernel/linux/linux-yocto.inc 7require recipes-kernel/linux/linux-yocto.inc
8 8
9LINUX_VERSION ?= "5.4.153" 9LINUX_VERSION ?= "5.4.178"
10LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" 10LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
11 11
12DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}" 12DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}"
@@ -15,9 +15,9 @@ DEPENDS += "openssl-native util-linux-native"
15KMETA = "kernel-meta" 15KMETA = "kernel-meta"
16KCONF_BSP_AUDIT_LEVEL = "2" 16KCONF_BSP_AUDIT_LEVEL = "2"
17 17
18SRCREV_machine_qemuarm ?= "fed16a9b9cb56ce639eeddeedd756ad5207fa89e" 18SRCREV_machine_qemuarm ?= "f6e09845d8bf3c307da395497b21c1ff17ef575c"
19SRCREV_machine ?= "942b0cc9a1ff13a66016167d4437f7694e96d04e" 19SRCREV_machine ?= "a7ba52065be4401b5d73b6b020770f7d260b7bf1"
20SRCREV_meta ?= "9e3ab4e615b651c1b63d4f0cce71da79a3e89763" 20SRCREV_meta ?= "e8c675c7e11fbd96cd812dfb9f4f6fb6f92b6abb"
21 21
22PV = "${LINUX_VERSION}+git${SRCPV}" 22PV = "${LINUX_VERSION}+git${SRCPV}"
23 23
diff --git a/meta/recipes-kernel/linux/linux-yocto_5.10.bb b/meta/recipes-kernel/linux/linux-yocto_5.10.bb
index 2652d01c26..5ce504812f 100644
--- a/meta/recipes-kernel/linux/linux-yocto_5.10.bb
+++ b/meta/recipes-kernel/linux/linux-yocto_5.10.bb
@@ -13,17 +13,17 @@ KBRANCH_qemux86 ?= "v5.10/standard/base"
13KBRANCH_qemux86-64 ?= "v5.10/standard/base" 13KBRANCH_qemux86-64 ?= "v5.10/standard/base"
14KBRANCH_qemumips64 ?= "v5.10/standard/mti-malta64" 14KBRANCH_qemumips64 ?= "v5.10/standard/mti-malta64"
15 15
16SRCREV_machine_qemuarm ?= "f98b917d7826304daeecf11cc52be2562a9304ff" 16SRCREV_machine_qemuarm ?= "2ef8231651bb6a4c79b307f59a794b92238546ec"
17SRCREV_machine_qemuarm64 ?= "13ff8a3ae368724e008e3bcd77833611de7962b2" 17SRCREV_machine_qemuarm64 ?= "00684b441f15d202c5849eed164a9b3b94a5c1e8"
18SRCREV_machine_qemumips ?= "7b94dec2b0f5b582b97cdb3ac97fe153559869e4" 18SRCREV_machine_qemumips ?= "661a4f517906253e074fe301d68ff1e6b6968e9f"
19SRCREV_machine_qemuppc ?= "652531fb0cc8eb3607109bb8d878253be2d3d534" 19SRCREV_machine_qemuppc ?= "bff933cb7a11019c64e6034c48ab79453f75b99e"
20SRCREV_machine_qemuriscv64 ?= "2daa192783edd4974da8e900c0dc93186e57a838" 20SRCREV_machine_qemuriscv64 ?= "763c0dbc0458ebcb1d06afe2f324925f0f61bd27"
21SRCREV_machine_qemuriscv32 ?= "2daa192783edd4974da8e900c0dc93186e57a838" 21SRCREV_machine_qemuriscv32 ?= "763c0dbc0458ebcb1d06afe2f324925f0f61bd27"
22SRCREV_machine_qemux86 ?= "2daa192783edd4974da8e900c0dc93186e57a838" 22SRCREV_machine_qemux86 ?= "763c0dbc0458ebcb1d06afe2f324925f0f61bd27"
23SRCREV_machine_qemux86-64 ?= "2daa192783edd4974da8e900c0dc93186e57a838" 23SRCREV_machine_qemux86-64 ?= "763c0dbc0458ebcb1d06afe2f324925f0f61bd27"
24SRCREV_machine_qemumips64 ?= "4c817df0fd06350e18693551699c33361e16a193" 24SRCREV_machine_qemumips64 ?= "7a89b456542ff1fa0ab71fa4a2ae6f04281f3a2d"
25SRCREV_machine ?= "2daa192783edd4974da8e900c0dc93186e57a838" 25SRCREV_machine ?= "763c0dbc0458ebcb1d06afe2f324925f0f61bd27"
26SRCREV_meta ?= "a0238f7f4f2222d08bb18147bb5e24cc877b0546" 26SRCREV_meta ?= "24ab54209a8822aad92afe2c51ea5b95f5175394"
27 27
28# remap qemuarm to qemuarma15 for the 5.8 kernel 28# remap qemuarm to qemuarma15 for the 5.8 kernel
29# KMACHINE_qemuarm ?= "qemuarma15" 29# KMACHINE_qemuarm ?= "qemuarma15"
@@ -32,11 +32,11 @@ SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;name=machine;branch=${KBRA
32 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.10;destsuffix=${KMETA}" 32 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.10;destsuffix=${KMETA}"
33 33
34LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46" 34LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
35LINUX_VERSION ?= "5.10.78" 35LINUX_VERSION ?= "5.10.107"
36 36
37DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}" 37DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}"
38DEPENDS += "openssl-native util-linux-native" 38DEPENDS += "openssl-native util-linux-native"
39DEPENDS += "gmp-native" 39DEPENDS += "gmp-native libmpc-native"
40 40
41PV = "${LINUX_VERSION}+git${SRCPV}" 41PV = "${LINUX_VERSION}+git${SRCPV}"
42 42
diff --git a/meta/recipes-kernel/linux/linux-yocto_5.4.bb b/meta/recipes-kernel/linux/linux-yocto_5.4.bb
index 4418a85ba4..ae9dbca3af 100644
--- a/meta/recipes-kernel/linux/linux-yocto_5.4.bb
+++ b/meta/recipes-kernel/linux/linux-yocto_5.4.bb
@@ -12,16 +12,16 @@ KBRANCH_qemux86 ?= "v5.4/standard/base"
12KBRANCH_qemux86-64 ?= "v5.4/standard/base" 12KBRANCH_qemux86-64 ?= "v5.4/standard/base"
13KBRANCH_qemumips64 ?= "v5.4/standard/mti-malta64" 13KBRANCH_qemumips64 ?= "v5.4/standard/mti-malta64"
14 14
15SRCREV_machine_qemuarm ?= "7a9ca83b483c096e6bd5e1b99cca7fe2fb79fd1a" 15SRCREV_machine_qemuarm ?= "b3ee7c62bf5a5ce3c7e30aff6c3dd9f70a847a28"
16SRCREV_machine_qemuarm64 ?= "d2ea3664c5872b3046a2aa970035de51e359922f" 16SRCREV_machine_qemuarm64 ?= "bf6581eba15cb43af60fda7053edaf66990c18ac"
17SRCREV_machine_qemumips ?= "118685bb5211a7740de6bd419c68eb34728f8770" 17SRCREV_machine_qemumips ?= "05580fff716df568dc3f737b288e0e514a908572"
18SRCREV_machine_qemuppc ?= "7e8785640416d3c6382f91a3f88e0eca14f0a8b5" 18SRCREV_machine_qemuppc ?= "0a016b0775980f67d686e47cc8637adec46856dc"
19SRCREV_machine_qemuriscv64 ?= "d54d61f9e363806a987c9ab01df0e66a31d4ead5" 19SRCREV_machine_qemuriscv64 ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
20SRCREV_machine_qemux86 ?= "d54d61f9e363806a987c9ab01df0e66a31d4ead5" 20SRCREV_machine_qemux86 ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
21SRCREV_machine_qemux86-64 ?= "d54d61f9e363806a987c9ab01df0e66a31d4ead5" 21SRCREV_machine_qemux86-64 ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
22SRCREV_machine_qemumips64 ?= "bd5e23a14522aa81e0f0ee37f976edd108669eb5" 22SRCREV_machine_qemumips64 ?= "68f35eeca08d2a681495fd3a7b823ac34d9a97bc"
23SRCREV_machine ?= "d54d61f9e363806a987c9ab01df0e66a31d4ead5" 23SRCREV_machine ?= "e2020dbe2ccaef50d7e8f37a5bf08c68a006a064"
24SRCREV_meta ?= "9e3ab4e615b651c1b63d4f0cce71da79a3e89763" 24SRCREV_meta ?= "e8c675c7e11fbd96cd812dfb9f4f6fb6f92b6abb"
25 25
26# remap qemuarm to qemuarma15 for the 5.4 kernel 26# remap qemuarm to qemuarma15 for the 5.4 kernel
27# KMACHINE_qemuarm ?= "qemuarma15" 27# KMACHINE_qemuarm ?= "qemuarma15"
@@ -30,7 +30,7 @@ SRC_URI = "git://git.yoctoproject.org/linux-yocto.git;name=machine;branch=${KBRA
30 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.4;destsuffix=${KMETA}" 30 git://git.yoctoproject.org/yocto-kernel-cache;type=kmeta;name=meta;branch=yocto-5.4;destsuffix=${KMETA}"
31 31
32LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814" 32LIC_FILES_CHKSUM = "file://COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
33LINUX_VERSION ?= "5.4.153" 33LINUX_VERSION ?= "5.4.178"
34 34
35DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}" 35DEPENDS += "${@bb.utils.contains('ARCH', 'x86', 'elfutils-native', '', d)}"
36DEPENDS += "openssl-native util-linux-native" 36DEPENDS += "openssl-native util-linux-native"
diff --git a/meta/recipes-kernel/lttng/lttng-modules_2.12.6.bb b/meta/recipes-kernel/lttng/lttng-modules_2.12.8.bb
index 1dff2b05f7..eff97f27af 100644
--- a/meta/recipes-kernel/lttng/lttng-modules_2.12.6.bb
+++ b/meta/recipes-kernel/lttng/lttng-modules_2.12.8.bb
@@ -13,7 +13,7 @@ SRC_URI = "https://lttng.org/files/${BPN}/${BPN}-${PV}.tar.bz2 \
13 file://Makefile-Do-not-fail-if-CONFIG_TRACEPOINTS-is-not-en.patch \ 13 file://Makefile-Do-not-fail-if-CONFIG_TRACEPOINTS-is-not-en.patch \
14 " 14 "
15 15
16SRC_URI[sha256sum] = "95ac2a2cf92d85d23ffbdaca6a1ec0d7c167211d1e0fb850ab90004a3f475eaa" 16SRC_URI[sha256sum] = "1302005a982fd4a15cc4843866971008546939f65660023d7762aa046d4b9213"
17 17
18export INSTALL_MOD_DIR="kernel/lttng-modules" 18export INSTALL_MOD_DIR="kernel/lttng-modules"
19 19
diff --git a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2021.08.28.bb b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2022.02.18.bb
index b1cad01a25..2d7e5dad9d 100644
--- a/meta/recipes-kernel/wireless-regdb/wireless-regdb_2021.08.28.bb
+++ b/meta/recipes-kernel/wireless-regdb/wireless-regdb_2022.02.18.bb
@@ -5,7 +5,7 @@ LICENSE = "ISC"
5LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c" 5LIC_FILES_CHKSUM = "file://LICENSE;md5=07c4f6dea3845b02a18dc00c8c87699c"
6 6
7SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz" 7SRC_URI = "https://www.kernel.org/pub/software/network/${BPN}/${BP}.tar.xz"
8SRC_URI[sha256sum] = "cff370c410d1e6d316ae0a7fa8ac6278fdf1efca5d3d664aca7cfd2aafa54446" 8SRC_URI[sha256sum] = "8828c25a4ee25020044004f57374bb9deac852809fad70f8d3d01770bf9ac97f"
9 9
10inherit bin_package allarch 10inherit bin_package allarch
11 11
diff --git a/meta/recipes-multimedia/flac/flac/CVE-2021-0561.patch b/meta/recipes-multimedia/flac/flac/CVE-2021-0561.patch
new file mode 100644
index 0000000000..b48663ae42
--- /dev/null
+++ b/meta/recipes-multimedia/flac/flac/CVE-2021-0561.patch
@@ -0,0 +1,41 @@
1From e1575e4a7c5157cbf4e4a16dbd39b74f7174c7be Mon Sep 17 00:00:00 2001
2From: Neelkamal Semwal <neelkamal.semwal@ittiam.com>
3Date: Fri, 18 Dec 2020 22:28:36 +0530
4Subject: [PATCH] libFlac: Exit at EOS in verify mode
5
6When verify mode is enabled, once decoder flags end of stream,
7encode processing is considered complete.
8
9CVE-2021-0561
10
11Signed-off-by: Ralph Giles <giles@thaumas.net>
12
13Upstream-Status: Backport
14CVE: CVE-2021-0561
15
16Reference to upstream patch:
17https://github.com/xiph/flac/commit/e1575e4a7c5157cbf4e4a16dbd39b74f7174c7be
18
19Signed-off-by: Li Wang <li.wang@windriver.com>
20---
21 src/libFLAC/stream_encoder.c | 4 +++-
22 1 file changed, 3 insertions(+), 1 deletion(-)
23
24diff --git a/src/libFLAC/stream_encoder.c b/src/libFLAC/stream_encoder.c
25index 74387ec..8bb0ef3 100644
26--- a/src/libFLAC/stream_encoder.c
27+++ b/src/libFLAC/stream_encoder.c
28@@ -2610,7 +2610,9 @@ FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, uint32_t samples, FLAC
29 encoder->private_->verify.needs_magic_hack = true;
30 }
31 else {
32- if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)) {
33+ if(!FLAC__stream_decoder_process_single(encoder->private_->verify.decoder)
34+ || (!is_last_block
35+ && (FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_END_OF_STREAM))) {
36 FLAC__bitwriter_release_buffer(encoder->private_->frame);
37 FLAC__bitwriter_clear(encoder->private_->frame);
38 if(encoder->protected_->state != FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA)
39--
402.23.0
41
diff --git a/meta/recipes-multimedia/flac/flac_1.3.3.bb b/meta/recipes-multimedia/flac/flac_1.3.3.bb
index cb6692aedf..d3c352cc44 100644
--- a/meta/recipes-multimedia/flac/flac_1.3.3.bb
+++ b/meta/recipes-multimedia/flac/flac_1.3.3.bb
@@ -15,6 +15,7 @@ LIC_FILES_CHKSUM = "file://COPYING.FDL;md5=ad1419ecc56e060eccf8184a87c4285f \
15DEPENDS = "libogg" 15DEPENDS = "libogg"
16 16
17SRC_URI = "http://downloads.xiph.org/releases/flac/${BP}.tar.xz \ 17SRC_URI = "http://downloads.xiph.org/releases/flac/${BP}.tar.xz \
18 file://CVE-2021-0561.patch \
18" 19"
19 20
20SRC_URI[md5sum] = "26703ed2858c1fc9ffc05136d13daa69" 21SRC_URI[md5sum] = "26703ed2858c1fc9ffc05136d13daa69"
diff --git a/meta/recipes-multimedia/gstreamer/gst-devtools_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gst-devtools_1.18.6.bb
index 2a56967f7b..258a0e899c 100644
--- a/meta/recipes-multimedia/gstreamer/gst-devtools_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gst-devtools_1.18.6.bb
@@ -12,7 +12,7 @@ SRC_URI = "https://gstreamer.freedesktop.org/src/gst-devtools/gst-devtools-${PV}
12 file://0001-connect-has-a-different-signature-on-musl.patch \ 12 file://0001-connect-has-a-different-signature-on-musl.patch \
13 " 13 "
14 14
15SRC_URI[sha256sum] = "ffbd194c40912cb5e7fca2863648bf9dd8257b7af97d3a60c4fcd4efd8526ccf" 15SRC_URI[sha256sum] = "3725622c740a635452e54b79d065f963ab7706ca2403de6c43072ae7610a0de4"
16 16
17DEPENDS = "json-glib glib-2.0 glib-2.0-native gstreamer1.0 gstreamer1.0-plugins-base" 17DEPENDS = "json-glib glib-2.0 glib-2.0-native gstreamer1.0 gstreamer1.0-plugins-base"
18RRECOMMENDS_${PN} = "git" 18RRECOMMENDS_${PN} = "git"
diff --git a/meta/recipes-multimedia/gstreamer/gst-examples_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gst-examples_1.18.6.bb
index 4670ab34db..5af43d1eda 100644
--- a/meta/recipes-multimedia/gstreamer/gst-examples_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gst-examples_1.18.6.bb
@@ -12,7 +12,7 @@ SRC_URI = "git://gitlab.freedesktop.org/gstreamer/gst-examples.git;protocol=http
12 file://gst-player.desktop \ 12 file://gst-player.desktop \
13 " 13 "
14 14
15SRCREV = "959bb246a5b1f5f9c78557da11c3f22b42ff89c0" 15SRCREV = "70e4fcf4fc8ae19641aa990de5f37d758cdfcea4"
16 16
17S = "${WORKDIR}/git" 17S = "${WORKDIR}/git"
18 18
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.6.bb
index 6a84f92f31..6229bb4d62 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-libav_1.18.6.bb
@@ -12,7 +12,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=6762ed442b3822387a51c92d928ead0d \
12 " 12 "
13 13
14SRC_URI = "https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-${PV}.tar.xz" 14SRC_URI = "https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-${PV}.tar.xz"
15SRC_URI[sha256sum] = "344a463badca216c2cef6ee36f9510c190862bdee48dc4591c0a430df7e8c396" 15SRC_URI[sha256sum] = "e4e50dcd5a29441ae34de60d2221057e8064ed824bb6ca4dc0fd9ee88fbe9b81"
16 16
17S = "${WORKDIR}/gst-libav-${PV}" 17S = "${WORKDIR}/gst-libav-${PV}"
18 18
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.6.bb
index d38be035f9..04b5dcc4f4 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-omx_1.18.6.bb
@@ -10,7 +10,7 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=4fbd65380cdd255951079008b364516c \
10 10
11SRC_URI = "https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-${PV}.tar.xz" 11SRC_URI = "https://gstreamer.freedesktop.org/src/gst-omx/gst-omx-${PV}.tar.xz"
12 12
13SRC_URI[sha256sum] = "e35051cf891eb2f31d6fcf176ff37d985f97f33874ac31b0b3ad3b5b95035043" 13SRC_URI[sha256sum] = "b5281c938e959fd2418e989cfb6065fdd9fe5f6f87ee86236c9427166e708163"
14 14
15S = "${WORKDIR}/gst-omx-${PV}" 15S = "${WORKDIR}/gst-omx-${PV}"
16 16
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.6.bb
index ce2082ee32..63e3488e9e 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-bad_1.18.6.bb
@@ -11,7 +11,7 @@ SRC_URI = "https://gstreamer.freedesktop.org/src/gst-plugins-bad/gst-plugins-bad
11 file://0004-opencv-resolve-missing-opencv-data-dir-in-yocto-buil.patch \ 11 file://0004-opencv-resolve-missing-opencv-data-dir-in-yocto-buil.patch \
12 file://0005-msdk-fix-includedir-path.patch \ 12 file://0005-msdk-fix-includedir-path.patch \
13 " 13 "
14SRC_URI[sha256sum] = "74e806bc5595b18c70e9ca93571e27e79dfb808e5d2e7967afa952b52e99c85f" 14SRC_URI[sha256sum] = "0b1b50ac6311f0c510248b6cd64d6d3c94369344828baa602db85ded5bc70ec9"
15 15
16S = "${WORKDIR}/gst-plugins-bad-${PV}" 16S = "${WORKDIR}/gst-plugins-bad-${PV}"
17 17
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.6.bb
index 728a99e08b..4e7fc62ec7 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-base_1.18.6.bb
@@ -12,7 +12,7 @@ SRC_URI = "https://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-ba
12 file://0002-ssaparse-enhance-SSA-text-lines-parsing.patch \ 12 file://0002-ssaparse-enhance-SSA-text-lines-parsing.patch \
13 file://0004-glimagesink-Downrank-to-marginal.patch \ 13 file://0004-glimagesink-Downrank-to-marginal.patch \
14 " 14 "
15SRC_URI[sha256sum] = "29e53229a84d01d722f6f6db13087231cdf6113dd85c25746b9b58c3d68e8323" 15SRC_URI[sha256sum] = "56a9ff2fe9e6603b9e658cf6897d412a173d2180829fe01e92568549c6bd0f5b"
16 16
17S = "${WORKDIR}/gst-plugins-base-${PV}" 17S = "${WORKDIR}/gst-plugins-base-${PV}"
18 18
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-rtpjitterbuffer-Fix-parsing-of-the-mediaclk-direct-f.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-rtpjitterbuffer-Fix-parsing-of-the-mediaclk-direct-f.patch
deleted file mode 100644
index 14a9fe23aa..0000000000
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good/0002-rtpjitterbuffer-Fix-parsing-of-the-mediaclk-direct-f.patch
+++ /dev/null
@@ -1,33 +0,0 @@
1From ec1949dffd931d0ec7e4f67108a08ab1e2af0cfe Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian@centricular.com>
3Date: Tue, 16 Mar 2021 19:25:36 +0200
4Subject: [PATCH] rtpjitterbuffer: Fix parsing of the mediaclk:direct= field
5
6Due to an off-by-one when parsing the string, the most significant digit
7or the clock offset was skipped when parsing the offset.
8
9Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/910>
10
11Upstream-Status: Backport [b5bb4ede3a42273fafc1054f9cf106ca527e3c26]
12
13Signed-off-by: Jose Quaresma <quaresma.jose@gmail.com>
14---
15 gst/rtpmanager/gstrtpjitterbuffer.c | 2 +-
16 1 file changed, 1 insertion(+), 1 deletion(-)
17
18diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c
19index 60d8ad875..02fe15adc 100644
20--- a/gst/rtpmanager/gstrtpjitterbuffer.c
21+++ b/gst/rtpmanager/gstrtpjitterbuffer.c
22@@ -1534,7 +1534,7 @@ gst_jitter_buffer_sink_parse_caps (GstRtpJitterBuffer * jitterbuffer,
23 GST_DEBUG_OBJECT (jitterbuffer, "Got media clock %s", mediaclk);
24
25 if (!g_str_has_prefix (mediaclk, "direct=") ||
26- !g_ascii_string_to_unsigned (&mediaclk[8], 10, 0, G_MAXUINT64,
27+ !g_ascii_string_to_unsigned (&mediaclk[7], 10, 0, G_MAXUINT64,
28 &clock_offset, NULL))
29 GST_FIXME_OBJECT (jitterbuffer, "Unsupported media clock");
30 if (strstr (mediaclk, "rate=") != NULL) {
31--
322.31.0
33
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.6.bb
index 07cacdc68a..72ad8eff08 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-good_1.18.6.bb
@@ -6,10 +6,9 @@ BUGTRACKER = "https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/issues
6 6
7SRC_URI = "https://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-${PV}.tar.xz \ 7SRC_URI = "https://gstreamer.freedesktop.org/src/gst-plugins-good/gst-plugins-good-${PV}.tar.xz \
8 file://0001-qt-include-ext-qt-gstqtgl.h-instead-of-gst-gl-gstglf.patch \ 8 file://0001-qt-include-ext-qt-gstqtgl.h-instead-of-gst-gl-gstglf.patch \
9 file://0002-rtpjitterbuffer-Fix-parsing-of-the-mediaclk-direct-f.patch \
10 " 9 "
11 10
12SRC_URI[sha256sum] = "b6e50e3a9bbcd56ee6ec71c33aa8332cc9c926b0c1fae995aac8b3040ebe39b0" 11SRC_URI[sha256sum] = "26723ac01fcb360ade1f41d168c7c322d8af4ceb7e55c8c12ed2690d06a76eed"
13 12
14S = "${WORKDIR}/gst-plugins-good-${PV}" 13S = "${WORKDIR}/gst-plugins-good-${PV}"
15 14
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.6.bb
index 932fa7f6fb..4774a17c1e 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-plugins-ugly_1.18.6.bb
@@ -13,7 +13,7 @@ LICENSE_FLAGS = "commercial"
13SRC_URI = " \ 13SRC_URI = " \
14 https://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-${PV}.tar.xz \ 14 https://gstreamer.freedesktop.org/src/gst-plugins-ugly/gst-plugins-ugly-${PV}.tar.xz \
15 " 15 "
16SRC_URI[sha256sum] = "218df0ce0d31e8ca9cdeb01a3b0c573172cc9c21bb3d41811c7820145623d13c" 16SRC_URI[sha256sum] = "4969c409cb6a88317d2108b8577108e18623b2333d7b587ae3f39459c70e3a7f"
17 17
18S = "${WORKDIR}/gst-plugins-ugly-${PV}" 18S = "${WORKDIR}/gst-plugins-ugly-${PV}"
19 19
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.6.bb
index 49de3dac84..1a3ae5dde6 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-python_1.18.6.bb
@@ -8,7 +8,7 @@ LICENSE = "LGPLv2.1"
8LIC_FILES_CHKSUM = "file://COPYING;md5=c34deae4e395ca07e725ab0076a5f740" 8LIC_FILES_CHKSUM = "file://COPYING;md5=c34deae4e395ca07e725ab0076a5f740"
9 9
10SRC_URI = "https://gstreamer.freedesktop.org/src/${PNREAL}/${PNREAL}-${PV}.tar.xz" 10SRC_URI = "https://gstreamer.freedesktop.org/src/${PNREAL}/${PNREAL}-${PV}.tar.xz"
11SRC_URI[sha256sum] = "cb68e08a7e825e08b83a12a22dcd6e4f1b328a7b02a7ac84f42f68f4ddc7098e" 11SRC_URI[sha256sum] = "bdc0ea22fbd7335ad9decc151561aacc53c51206a9735b81eac700ce5b0bbd4a"
12 12
13DEPENDS = "gstreamer1.0 gstreamer1.0-plugins-base python3-pygobject" 13DEPENDS = "gstreamer1.0 gstreamer1.0-plugins-base python3-pygobject"
14RDEPENDS_${PN} += "gstreamer1.0 gstreamer1.0-plugins-base python3-pygobject" 14RDEPENDS_${PN} += "gstreamer1.0 gstreamer1.0-plugins-base python3-pygobject"
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.6.bb
index f7bfe98985..f105713f33 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-rtsp-server_1.18.6.bb
@@ -10,7 +10,7 @@ PNREAL = "gst-rtsp-server"
10 10
11SRC_URI = "https://gstreamer.freedesktop.org/src/${PNREAL}/${PNREAL}-${PV}.tar.xz" 11SRC_URI = "https://gstreamer.freedesktop.org/src/${PNREAL}/${PNREAL}-${PV}.tar.xz"
12 12
13SRC_URI[sha256sum] = "a46bb8de40b971a048580279d2660e616796f871ad3ed00c8a95fe4d273a6c94" 13SRC_URI[sha256sum] = "826f32afbcf94b823541efcac4a0dacdb62f6145ef58f363095749f440262be9"
14 14
15S = "${WORKDIR}/${PNREAL}-${PV}" 15S = "${WORKDIR}/${PNREAL}-${PV}"
16 16
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.6.bb
index a268d79541..a604b5ebce 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0-vaapi_1.18.6.bb
@@ -11,7 +11,7 @@ LIC_FILES_CHKSUM = "file://COPYING.LIB;md5=4fbd65380cdd255951079008b364516c"
11 11
12SRC_URI = "https://gstreamer.freedesktop.org/src/${REALPN}/${REALPN}-${PV}.tar.xz" 12SRC_URI = "https://gstreamer.freedesktop.org/src/${REALPN}/${REALPN}-${PV}.tar.xz"
13 13
14SRC_URI[sha256sum] = "92db98af86f3150d429c9ab17e88d2364f9c07a140c8f445ed739e8f10252aea" 14SRC_URI[sha256sum] = "ab6270f1e5e4546fbe6f5ea246d86ca3d196282eb863d46e6cdcc96f867449e0"
15 15
16S = "${WORKDIR}/${REALPN}-${PV}" 16S = "${WORKDIR}/${REALPN}-${PV}"
17DEPENDS = "libva gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad" 17DEPENDS = "libva gstreamer1.0 gstreamer1.0-plugins-base gstreamer1.0-plugins-bad"
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-Remove-unused-valgrind-detection.patch b/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-Remove-unused-valgrind-detection.patch
index 96abef17b0..5121044734 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-Remove-unused-valgrind-detection.patch
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0/0002-Remove-unused-valgrind-detection.patch
@@ -1,4 +1,4 @@
1From 598d108e2c438d8f2ecd3bf948fa3ebbd3681490 Mon Sep 17 00:00:00 2001 1From e275ba2bd854ac15a4b65a8f07d9f042021950da Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= <tim@centricular.com> 2From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= <tim@centricular.com>
3Date: Fri, 14 Aug 2020 16:38:26 +0100 3Date: Fri, 14 Aug 2020 16:38:26 +0100
4Subject: [PATCH 2/3] Remove unused valgrind detection 4Subject: [PATCH 2/3] Remove unused valgrind detection
@@ -19,7 +19,7 @@ Signed-off-by: Jose Quaresma <quaresma.jose@gmail.com>
19 3 files changed, 42 deletions(-) 19 3 files changed, 42 deletions(-)
20 20
21diff --git a/gst/gst_private.h b/gst/gst_private.h 21diff --git a/gst/gst_private.h b/gst/gst_private.h
22index eefd044d9..8252ede51 100644 22index eefd044..8252ede 100644
23--- a/gst/gst_private.h 23--- a/gst/gst_private.h
24+++ b/gst/gst_private.h 24+++ b/gst/gst_private.h
25@@ -116,8 +116,6 @@ G_GNUC_INTERNAL gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin 25@@ -116,8 +116,6 @@ G_GNUC_INTERNAL gboolean _priv_plugin_deps_env_vars_changed (GstPlugin * plugin
@@ -32,12 +32,12 @@ index eefd044d9..8252ede51 100644
32 G_GNUC_INTERNAL void _priv_gst_quarks_initialize (void); 32 G_GNUC_INTERNAL void _priv_gst_quarks_initialize (void);
33 G_GNUC_INTERNAL void _priv_gst_mini_object_initialize (void); 33 G_GNUC_INTERNAL void _priv_gst_mini_object_initialize (void);
34diff --git a/gst/gstinfo.c b/gst/gstinfo.c 34diff --git a/gst/gstinfo.c b/gst/gstinfo.c
35index 5d317877b..097f8b20d 100644 35index eea1a21..d3035d6 100644
36--- a/gst/gstinfo.c 36--- a/gst/gstinfo.c
37+++ b/gst/gstinfo.c 37+++ b/gst/gstinfo.c
38@@ -305,36 +305,6 @@ static gboolean pretty_tags = PRETTY_TAGS_DEFAULT; 38@@ -305,36 +305,6 @@ static gboolean pretty_tags = PRETTY_TAGS_DEFAULT;
39 static volatile gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT; 39 static gint G_GNUC_MAY_ALIAS __default_level = GST_LEVEL_DEFAULT;
40 static volatile gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON; 40 static gint G_GNUC_MAY_ALIAS __use_color = GST_DEBUG_COLOR_MODE_ON;
41 41
42-/* FIXME: export this? */ 42-/* FIXME: export this? */
43-gboolean 43-gboolean
@@ -82,7 +82,7 @@ index 5d317877b..097f8b20d 100644
82 env = g_getenv ("GST_DEBUG_OPTIONS"); 82 env = g_getenv ("GST_DEBUG_OPTIONS");
83 if (env != NULL) { 83 if (env != NULL) {
84 if (strstr (env, "full_tags") || strstr (env, "full-tags")) 84 if (strstr (env, "full_tags") || strstr (env, "full-tags"))
85@@ -2503,12 +2470,6 @@ gst_debug_construct_win_color (guint colorinfo) 85@@ -2505,12 +2472,6 @@ gst_debug_construct_win_color (guint colorinfo)
86 return 0; 86 return 0;
87 } 87 }
88 88
@@ -96,7 +96,7 @@ index 5d317877b..097f8b20d 100644
96 _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file, 96 _gst_debug_dump_mem (GstDebugCategory * cat, const gchar * file,
97 const gchar * func, gint line, GObject * obj, const gchar * msg, 97 const gchar * func, gint line, GObject * obj, const gchar * msg,
98diff --git a/meson.build b/meson.build 98diff --git a/meson.build b/meson.build
99index ce1921aa4..7a84d0981 100644 99index 82a1728..42ae617 100644
100--- a/meson.build 100--- a/meson.build
101+++ b/meson.build 101+++ b/meson.build
102@@ -200,7 +200,6 @@ check_headers = [ 102@@ -200,7 +200,6 @@ check_headers = [
diff --git a/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.4.bb b/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.6.bb
index 8562070968..82fb476a47 100644
--- a/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.4.bb
+++ b/meta/recipes-multimedia/gstreamer/gstreamer1.0_1.18.6.bb
@@ -21,7 +21,7 @@ SRC_URI = "https://gstreamer.freedesktop.org/src/gstreamer/gstreamer-${PV}.tar.x
21 file://0003-meson-Add-option-for-installed-tests.patch \ 21 file://0003-meson-Add-option-for-installed-tests.patch \
22 file://0001-tests-seek-Don-t-use-too-strict-timeout-for-validati.patch \ 22 file://0001-tests-seek-Don-t-use-too-strict-timeout-for-validati.patch \
23 " 23 "
24SRC_URI[sha256sum] = "9aeec99b38e310817012aa2d1d76573b787af47f8a725a65b833880a094dfbc5" 24SRC_URI[sha256sum] = "4ec816010dd4d3a93cf470ad0a6f25315f52b204eb1d71dfa70ab8a1c3bd06e6"
25 25
26PACKAGECONFIG ??= "${@bb.utils.contains('PTEST_ENABLED', '1', 'tests', '', d)} \ 26PACKAGECONFIG ??= "${@bb.utils.contains('PTEST_ENABLED', '1', 'tests', '', d)} \
27 check \ 27 check \
diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2021-4156.patch b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2021-4156.patch
new file mode 100644
index 0000000000..b0ff1a0885
--- /dev/null
+++ b/meta/recipes-multimedia/libsndfile/libsndfile1/CVE-2021-4156.patch
@@ -0,0 +1,32 @@
1From 5adbc377cd90aa40f0cd56ae325ca70065a8aa19 Mon Sep 17 00:00:00 2001
2From: Changqing Li <changqing.li@windriver.com>
3Date: Thu, 13 Jan 2022 16:45:59 +0800
4Subject: [PATCH] flac: Fix improper buffer reusing
5
6CVE: CVE-2021-4156.patch
7Upstream-Status: Backport [https://github.com/libsndfile/libsndfile/issues/731]
8
9Signed-off-by: Changqing Li <changqing.li@windriver.com>
10---
11 src/flac.c | 4 ++++
12 1 file changed, 4 insertions(+)
13
14diff --git a/src/flac.c b/src/flac.c
15index 0be82ac..6548bba 100644
16--- a/src/flac.c
17+++ b/src/flac.c
18@@ -952,7 +952,11 @@ flac_read_loop (SF_PRIVATE *psf, unsigned len)
19 /* Decode some more. */
20 while (pflac->pos < pflac->len)
21 { if (FLAC__stream_decoder_process_single (pflac->fsd) == 0)
22+ { psf_log_printf (psf, "FLAC__stream_decoder_process_single returned false\n") ;
23+ /* Current frame is busted, so NULL the pointer. */
24+ pflac->frame = NULL ;
25 break ;
26+ }
27 state = FLAC__stream_decoder_get_state (pflac->fsd) ;
28 if (state >= FLAC__STREAM_DECODER_END_OF_STREAM)
29 { psf_log_printf (psf, "FLAC__stream_decoder_get_state returned %s\n", FLAC__StreamDecoderStateString [state]) ;
30--
312.17.1
32
diff --git a/meta/recipes-multimedia/libsndfile/libsndfile1_1.0.28.bb b/meta/recipes-multimedia/libsndfile/libsndfile1_1.0.28.bb
index 044881a859..8eb007884e 100644
--- a/meta/recipes-multimedia/libsndfile/libsndfile1_1.0.28.bb
+++ b/meta/recipes-multimedia/libsndfile/libsndfile1_1.0.28.bb
@@ -20,6 +20,7 @@ SRC_URI = "http://www.mega-nerd.com/libsndfile/files/libsndfile-${PV}.tar.gz \
20 file://CVE-2017-12562.patch \ 20 file://CVE-2017-12562.patch \
21 file://CVE-2018-19758.patch \ 21 file://CVE-2018-19758.patch \
22 file://CVE-2019-3832.patch \ 22 file://CVE-2019-3832.patch \
23 file://CVE-2021-4156.patch \
23 " 24 "
24 25
25SRC_URI[md5sum] = "646b5f98ce89ac60cdb060fcd398247c" 26SRC_URI[md5sum] = "646b5f98ce89ac60cdb060fcd398247c"
diff --git a/meta/recipes-multimedia/speex/speex/CVE-2020-23903.patch b/meta/recipes-multimedia/speex/speex/CVE-2020-23903.patch
new file mode 100644
index 0000000000..eb16e95ffc
--- /dev/null
+++ b/meta/recipes-multimedia/speex/speex/CVE-2020-23903.patch
@@ -0,0 +1,30 @@
1Backport patch to fix CVE-2020-23903.
2
3CVE: CVE-2020-23903
4Upstream-Status: Backport [https://github.com/xiph/speex/commit/870ff84]
5
6Signed-off-by: Kai Kang <kai.kang@windriver.com>
7
8From 870ff845b32f314aec0036641ffe18aba4916887 Mon Sep 17 00:00:00 2001
9From: Tristan Matthews <tmatth@videolan.org>
10Date: Mon, 13 Jul 2020 23:25:03 -0400
11Subject: [PATCH] wav_io: guard against invalid channel numbers
12
13Fixes #13
14---
15 src/wav_io.c | 2 +-
16 1 file changed, 1 insertion(+), 1 deletion(-)
17
18diff --git a/src/wav_io.c b/src/wav_io.c
19index b5183015..09d62eb0 100644
20--- a/src/wav_io.c
21+++ b/src/wav_io.c
22@@ -111,7 +111,7 @@ int read_wav_header(FILE *file, int *rate, int *channels, int *format, spx_int32
23 stmp = le_short(stmp);
24 *channels = stmp;
25
26- if (stmp>2)
27+ if (stmp>2 || stmp<1)
28 {
29 fprintf (stderr, "Only mono and (intensity) stereo supported\n");
30 return -1;
diff --git a/meta/recipes-multimedia/speex/speex_1.2.0.bb b/meta/recipes-multimedia/speex/speex_1.2.0.bb
index 3a0911d6f8..ea475f0f1b 100644
--- a/meta/recipes-multimedia/speex/speex_1.2.0.bb
+++ b/meta/recipes-multimedia/speex/speex_1.2.0.bb
@@ -7,7 +7,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=314649d8ba9dd7045dfb6683f298d0a8 \
7 file://include/speex/speex.h;beginline=1;endline=34;md5=ef8c8ea4f7198d71cf3509c6ed05ea50" 7 file://include/speex/speex.h;beginline=1;endline=34;md5=ef8c8ea4f7198d71cf3509c6ed05ea50"
8DEPENDS = "libogg speexdsp" 8DEPENDS = "libogg speexdsp"
9 9
10SRC_URI = "http://downloads.xiph.org/releases/speex/speex-${PV}.tar.gz" 10SRC_URI = "http://downloads.xiph.org/releases/speex/speex-${PV}.tar.gz \
11 file://CVE-2020-23903.patch \
12 "
11UPSTREAM_CHECK_REGEX = "speex-(?P<pver>\d+(\.\d+)+)\.tar" 13UPSTREAM_CHECK_REGEX = "speex-(?P<pver>\d+(\.\d+)+)\.tar"
12 14
13SRC_URI[md5sum] = "8ab7bb2589110dfaf0ed7fa7757dc49c" 15SRC_URI[md5sum] = "8ab7bb2589110dfaf0ed7fa7757dc49c"
diff --git a/meta/recipes-sato/webkit/webkitgtk/CVE-2021-42762.patch b/meta/recipes-sato/webkit/webkitgtk/CVE-2021-42762.patch
new file mode 100644
index 0000000000..1d012271cb
--- /dev/null
+++ b/meta/recipes-sato/webkit/webkitgtk/CVE-2021-42762.patch
@@ -0,0 +1,468 @@
1Backport and rebase patch to fix CVE-2021-42762 for webkitgtk 2.30.5.
2
3CVE: CVE-2021-42762
4Upstream-Status: Backport [https://trac.webkit.org/changeset/284451/webkit]
5
6Ref:
7* https://bugs.webkit.org/show_bug.cgi?id=231479#c8
8
9Signed-off-by: Kai Kang <kai.kang@windriver.com>
10
11From 035ac439855c7bef0a4525897f783121e4a6055c Mon Sep 17 00:00:00 2001
12From: Michael Catanzaro <mcatanzaro@gnome.org>
13Date: Tue, 19 Oct 2021 14:27:17 +0000
14Subject: [PATCH] Update seccomp filters with latest changes from flatpak
15 https://bugs.webkit.org/show_bug.cgi?id=231479
16
17Patch by Michael Catanzaro <mcatanzaro@gnome.org> on 2021-10-19
18Reviewed by Adrian Perez de Castro.
19
20Additionally, let's fix a minor inconsistency in our error-handling code: all but one of
21our codepaths carefully free and close resources, but the process is about to crash so
22there's not really any reason to do so. The code is slightly simpler if we don't bother.
23
24The seemingly-extraneous include order changes are required to placate the style checker.
25
26* UIProcess/Launcher/glib/BubblewrapLauncher.cpp:
27(WebKit::seccompStrerror):
28(WebKit::setupSeccomp):
29* UIProcess/Launcher/glib/Syscalls.h: Added.
30
31Canonical link: https://commits.webkit.org/243211@main
32git-svn-id: https://svn.webkit.org/repository/webkit/trunk@284451 268f45cc-cd09-0410-ab3c-d52691b4dbfc
33---
34 .../UIProcess/Launcher/glib/BubblewrapLauncher.cpp | 139 +++++++++-----
35 Source/WebKit/UIProcess/Launcher/glib/Syscalls.h | 200 +++++++++++++++++++++
36 2 files changed, 293 insertions(+), 46 deletions(-)
37
38diff --git a/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp b/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp
39index 889388ac..c2f7e502 100644
40--- a/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp
41+++ b/Source/WebKit/UIProcess/Launcher/glib/BubblewrapLauncher.cpp
42@@ -25,11 +25,18 @@
43 #include <glib.h>
44 #include <seccomp.h>
45 #include <sys/ioctl.h>
46+#include <sys/mman.h>
47 #include <wtf/FileSystem.h>
48 #include <wtf/glib/GLibUtilities.h>
49 #include <wtf/glib/GRefPtr.h>
50 #include <wtf/glib/GUniquePtr.h>
51
52+#if !defined(MFD_ALLOW_SEALING) && HAVE(LINUX_MEMFD_H)
53+#include <linux/memfd.h>
54+#endif
55+
56+#include "Syscalls.h"
57+
58 #if PLATFORM(GTK)
59 #include "WaylandCompositor.h"
60 #endif
61@@ -40,13 +47,7 @@
62 #define BASE_DIRECTORY "wpe"
63 #endif
64
65-#include <sys/mman.h>
66-
67-#ifndef MFD_ALLOW_SEALING
68-
69-#if HAVE(LINUX_MEMFD_H)
70-
71-#include <linux/memfd.h>
72+#if !defined(MFD_ALLOW_SEALING) && HAVE(LINUX_MEMFD_H)
73
74 // These defines were added in glibc 2.27, the same release that added memfd_create.
75 // But the kernel added all of this in Linux 3.17. So it's totally safe for us to
76@@ -65,9 +66,7 @@ static int memfd_create(const char* name, unsigned flags)
77 {
78 return syscall(__NR_memfd_create, name, flags);
79 }
80-#endif // #if HAVE(LINUX_MEMFD_H)
81-
82-#endif // #ifndef MFD_ALLOW_SEALING
83+#endif // #if !defined(MFD_ALLOW_SEALING) && HAVE(LINUX_MEMFD_H)
84
85 namespace WebKit {
86 using namespace WebCore;
87@@ -573,6 +572,28 @@ static void bindSymlinksRealPath(Vector<CString>& args, const char* path)
88 }
89 }
90
91+// Translate a libseccomp error code into an error message. libseccomp
92+// mostly returns negative errno values such as -ENOMEM, but some
93+// standard errno values are used for non-standard purposes where their
94+// strerror() would be misleading.
95+static const char* seccompStrerror(int negativeErrno)
96+{
97+ RELEASE_ASSERT_WITH_MESSAGE(negativeErrno < 0, "Non-negative error value from libseccomp?");
98+ RELEASE_ASSERT_WITH_MESSAGE(negativeErrno > INT_MIN, "Out of range error value from libseccomp?");
99+
100+ switch (negativeErrno) {
101+ case -EDOM:
102+ return "Architecture-specific failure";
103+ case -EFAULT:
104+ return "Internal libseccomp failure (unknown syscall?)";
105+ case -ECANCELED:
106+ return "System failure beyond the control of libseccomp";
107+ }
108+
109+ // e.g. -ENOMEM: the result of strerror() is good enough
110+ return g_strerror(-negativeErrno);
111+}
112+
113 static int setupSeccomp()
114 {
115 // NOTE: This is shared code (flatpak-run.c - LGPLv2.1+)
116@@ -600,6 +621,10 @@ static int setupSeccomp()
117 // in common/flatpak-run.c
118 // https://git.gnome.org/browse/linux-user-chroot
119 // in src/setup-seccomp.c
120+ //
121+ // Other useful resources:
122+ // https://github.com/systemd/systemd/blob/HEAD/src/shared/seccomp-util.c
123+ // https://github.com/moby/moby/blob/HEAD/profiles/seccomp/default.json
124
125 #if defined(__s390__) || defined(__s390x__) || defined(__CRIS__)
126 // Architectures with CONFIG_CLONE_BACKWARDS2: the child stack
127@@ -613,47 +638,70 @@ static int setupSeccomp()
128 struct scmp_arg_cmp ttyArg = SCMP_A1(SCMP_CMP_MASKED_EQ, 0xFFFFFFFFu, TIOCSTI);
129 struct {
130 int scall;
131+ int errnum;
132 struct scmp_arg_cmp* arg;
133 } syscallBlockList[] = {
134 // Block dmesg
135- { SCMP_SYS(syslog), nullptr },
136+ { SCMP_SYS(syslog), EPERM, nullptr },
137 // Useless old syscall.
138- { SCMP_SYS(uselib), nullptr },
139+ { SCMP_SYS(uselib), EPERM, nullptr },
140 // Don't allow disabling accounting.
141- { SCMP_SYS(acct), nullptr },
142+ { SCMP_SYS(acct), EPERM, nullptr },
143 // 16-bit code is unnecessary in the sandbox, and modify_ldt is a
144 // historic source of interesting information leaks.
145- { SCMP_SYS(modify_ldt), nullptr },
146+ { SCMP_SYS(modify_ldt), EPERM, nullptr },
147 // Don't allow reading current quota use.
148- { SCMP_SYS(quotactl), nullptr },
149+ { SCMP_SYS(quotactl), EPERM, nullptr },
150
151 // Don't allow access to the kernel keyring.
152- { SCMP_SYS(add_key), nullptr },
153- { SCMP_SYS(keyctl), nullptr },
154- { SCMP_SYS(request_key), nullptr },
155+ { SCMP_SYS(add_key), EPERM, nullptr },
156+ { SCMP_SYS(keyctl), EPERM, nullptr },
157+ { SCMP_SYS(request_key), EPERM, nullptr },
158
159 // Scary VM/NUMA ops
160- { SCMP_SYS(move_pages), nullptr },
161- { SCMP_SYS(mbind), nullptr },
162- { SCMP_SYS(get_mempolicy), nullptr },
163- { SCMP_SYS(set_mempolicy), nullptr },
164- { SCMP_SYS(migrate_pages), nullptr },
165+ { SCMP_SYS(move_pages), EPERM, nullptr },
166+ { SCMP_SYS(mbind), EPERM, nullptr },
167+ { SCMP_SYS(get_mempolicy), EPERM, nullptr },
168+ { SCMP_SYS(set_mempolicy), EPERM, nullptr },
169+ { SCMP_SYS(migrate_pages), EPERM, nullptr },
170
171 // Don't allow subnamespace setups:
172- { SCMP_SYS(unshare), nullptr },
173- { SCMP_SYS(mount), nullptr },
174- { SCMP_SYS(pivot_root), nullptr },
175- { SCMP_SYS(clone), &cloneArg },
176+ { SCMP_SYS(unshare), EPERM, nullptr },
177+ { SCMP_SYS(setns), EPERM, nullptr },
178+ { SCMP_SYS(mount), EPERM, nullptr },
179+ { SCMP_SYS(umount), EPERM, nullptr },
180+ { SCMP_SYS(umount2), EPERM, nullptr },
181+ { SCMP_SYS(pivot_root), EPERM, nullptr },
182+ { SCMP_SYS(chroot), EPERM, nullptr },
183+ { SCMP_SYS(clone), EPERM, &cloneArg },
184
185 // Don't allow faking input to the controlling tty (CVE-2017-5226)
186- { SCMP_SYS(ioctl), &ttyArg },
187+ { SCMP_SYS(ioctl), EPERM, &ttyArg },
188+
189+ // seccomp can't look into clone3()'s struct clone_args to check whether
190+ // the flags are OK, so we have no choice but to block clone3().
191+ // Return ENOSYS so user-space will fall back to clone().
192+ // (GHSA-67h7-w3jq-vh4q; see also https://github.com/moby/moby/commit/9f6b562d)
193+ { SCMP_SYS(clone3), ENOSYS, nullptr },
194+
195+ // New mount manipulation APIs can also change our VFS. There's no
196+ // legitimate reason to do these in the sandbox, so block all of them
197+ // rather than thinking about which ones might be dangerous.
198+ // (GHSA-67h7-w3jq-vh4q)
199+ { SCMP_SYS(open_tree), ENOSYS, nullptr },
200+ { SCMP_SYS(move_mount), ENOSYS, nullptr },
201+ { SCMP_SYS(fsopen), ENOSYS, nullptr },
202+ { SCMP_SYS(fsconfig), ENOSYS, nullptr },
203+ { SCMP_SYS(fsmount), ENOSYS, nullptr },
204+ { SCMP_SYS(fspick), ENOSYS, nullptr },
205+ { SCMP_SYS(mount_setattr), ENOSYS, nullptr },
206
207 // Profiling operations; we expect these to be done by tools from outside
208 // the sandbox. In particular perf has been the source of many CVEs.
209- { SCMP_SYS(perf_event_open), nullptr },
210+ { SCMP_SYS(perf_event_open), EPERM, nullptr },
211 // Don't allow you to switch to bsd emulation or whatnot.
212- { SCMP_SYS(personality), nullptr },
213- { SCMP_SYS(ptrace), nullptr }
214+ { SCMP_SYS(personality), EPERM, nullptr },
215+ { SCMP_SYS(ptrace), EPERM, nullptr }
216 };
217
218 scmp_filter_ctx seccomp = seccomp_init(SCMP_ACT_ALLOW);
219@@ -661,29 +709,28 @@ static int setupSeccomp()
220 g_error("Failed to init seccomp");
221
222 for (auto& rule : syscallBlockList) {
223- int scall = rule.scall;
224 int r;
225 if (rule.arg)
226- r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), scall, 1, *rule.arg);
227+ r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(rule.errnum), rule.scall, 1, *rule.arg);
228 else
229- r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(EPERM), scall, 0);
230- if (r == -EFAULT) {
231- seccomp_release(seccomp);
232- g_error("Failed to add seccomp rule");
233- }
234+ r = seccomp_rule_add(seccomp, SCMP_ACT_ERRNO(rule.errnum), rule.scall, 0);
235+ // EFAULT means "internal libseccomp error", but in practice we get
236+ // this for syscall numbers added via Syscalls.h (flatpak-syscalls-private.h)
237+ // when trying to filter them on a non-native architecture, because
238+ // libseccomp cannot map the syscall number to a name and back to a
239+ // number for the non-native architecture.
240+ if (r == -EFAULT)
241+ g_info("Unable to block syscall %d: syscall not known to libseccomp?", rule.scall);
242+ else if (r < 0)
243+ g_error("Failed to block syscall %d: %s", rule.scall, seccompStrerror(r));
244 }
245
246 int tmpfd = memfd_create("seccomp-bpf", 0);
247- if (tmpfd == -1) {
248- seccomp_release(seccomp);
249+ if (tmpfd == -1)
250 g_error("Failed to create memfd: %s", g_strerror(errno));
251- }
252
253- if (seccomp_export_bpf(seccomp, tmpfd)) {
254- seccomp_release(seccomp);
255- close(tmpfd);
256- g_error("Failed to export seccomp bpf");
257- }
258+ if (int r = seccomp_export_bpf(seccomp, tmpfd))
259+ g_error("Failed to export seccomp bpf: %s", seccompStrerror(r));
260
261 if (lseek(tmpfd, 0, SEEK_SET) < 0)
262 g_error("lseek failed: %s", g_strerror(errno));
263diff --git a/Source/WebKit/UIProcess/Launcher/glib/Syscalls.h b/Source/WebKit/UIProcess/Launcher/glib/Syscalls.h
264new file mode 100644
265index 00000000..18dea9a9
266--- /dev/null
267+++ b/Source/WebKit/UIProcess/Launcher/glib/Syscalls.h
268@@ -0,0 +1,200 @@
269+/*
270+ * Copyright 2021 Collabora Ltd.
271+ * SPDX-License-Identifier: LGPL-2.1-or-later
272+ *
273+ * This program is free software; you can redistribute it and/or
274+ * modify it under the terms of the GNU Lesser General Public
275+ * License as published by the Free Software Foundation; either
276+ * version 2.1 of the License, or (at your option) any later version.
277+ *
278+ * This library is distributed in the hope that it will be useful,
279+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
280+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
281+ * Lesser General Public License for more details.
282+ *
283+ * You should have received a copy of the GNU Lesser General Public
284+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
285+ */
286+
287+// This file is a copy of flatpak-syscalls-private.h, reformatted a bit to placate WebKit's style checker.
288+//
289+// Upstream is here:
290+// https://github.com/flatpak/flatpak/blob/26b12484eb8a6219b9e7aa287b298a894b2f34ca/common/flatpak-syscalls-private.h
291+
292+#pragma once
293+
294+#include <sys/syscall.h>
295+
296+#if defined(_MIPS_SIM)
297+# if _MIPS_SIM == _MIPS_SIM_ABI32
298+# define FLATPAK_MISSING_SYSCALL_BASE 4000
299+# elif _MIPS_SIM == _MIPS_SIM_ABI64
300+# define FLATPAK_MISSING_SYSCALL_BASE 5000
301+# elif _MIPS_SIM == _MIPS_SIM_NABI32
302+# define FLATPAK_MISSING_SYSCALL_BASE 6000
303+# else
304+# error "Unknown MIPS ABI"
305+# endif
306+#endif
307+
308+#if defined(__ia64__)
309+# define FLATPAK_MISSING_SYSCALL_BASE 1024
310+#endif
311+
312+#if defined(__alpha__)
313+# define FLATPAK_MISSING_SYSCALL_BASE 110
314+#endif
315+
316+#if defined(__x86_64__) && defined(__ILP32__)
317+# define FLATPAK_MISSING_SYSCALL_BASE 0x40000000
318+#endif
319+
320+// FLATPAK_MISSING_SYSCALL_BASE:
321+//
322+// Number to add to the syscall numbers of recently-added syscalls
323+// to get the appropriate syscall for the current ABI.
324+#ifndef FLATPAK_MISSING_SYSCALL_BASE
325+# define FLATPAK_MISSING_SYSCALL_BASE 0
326+#endif
327+
328+#ifndef __NR_open_tree
329+# define __NR_open_tree (FLATPAK_MISSING_SYSCALL_BASE + 428)
330+#endif
331+#ifndef __SNR_open_tree
332+# define __SNR_open_tree __NR_open_tree
333+#endif
334+
335+#ifndef __NR_move_mount
336+# define __NR_move_mount (FLATPAK_MISSING_SYSCALL_BASE + 429)
337+#endif
338+#ifndef __SNR_move_mount
339+# define __SNR_move_mount __NR_move_mount
340+#endif
341+
342+#ifndef __NR_fsopen
343+# define __NR_fsopen (FLATPAK_MISSING_SYSCALL_BASE + 430)
344+#endif
345+#ifndef __SNR_fsopen
346+# define __SNR_fsopen __NR_fsopen
347+#endif
348+
349+#ifndef __NR_fsconfig
350+# define __NR_fsconfig (FLATPAK_MISSING_SYSCALL_BASE + 431)
351+#endif
352+#ifndef __SNR_fsconfig
353+# define __SNR_fsconfig __NR_fsconfig
354+#endif
355+
356+#ifndef __NR_fsmount
357+# define __NR_fsmount (FLATPAK_MISSING_SYSCALL_BASE + 432)
358+#endif
359+#ifndef __SNR_fsmount
360+# define __SNR_fsmount __NR_fsmount
361+#endif
362+
363+#ifndef __NR_fspick
364+# define __NR_fspick (FLATPAK_MISSING_SYSCALL_BASE + 433)
365+#endif
366+#ifndef __SNR_fspick
367+# define __SNR_fspick __NR_fspick
368+#endif
369+
370+#ifndef __NR_pidfd_open
371+# define __NR_pidfd_open (FLATPAK_MISSING_SYSCALL_BASE + 434)
372+#endif
373+#ifndef __SNR_pidfd_open
374+# define __SNR_pidfd_open __NR_pidfd_open
375+#endif
376+
377+#ifndef __NR_clone3
378+# define __NR_clone3 (FLATPAK_MISSING_SYSCALL_BASE + 435)
379+#endif
380+#ifndef __SNR_clone3
381+# define __SNR_clone3 __NR_clone3
382+#endif
383+
384+#ifndef __NR_close_range
385+# define __NR_close_range (FLATPAK_MISSING_SYSCALL_BASE + 436)
386+#endif
387+#ifndef __SNR_close_range
388+# define __SNR_close_range __NR_close_range
389+#endif
390+
391+#ifndef __NR_openat2
392+# define __NR_openat2 (FLATPAK_MISSING_SYSCALL_BASE + 437)
393+#endif
394+#ifndef __SNR_openat2
395+# define __SNR_openat2 __NR_openat2
396+#endif
397+
398+#ifndef __NR_pidfd_getfd
399+# define __NR_pidfd_getfd (FLATPAK_MISSING_SYSCALL_BASE + 438)
400+#endif
401+#ifndef __SNR_pidfd_getfd
402+# define __SNR_pidfd_getfd __NR_pidfd_getfd
403+#endif
404+
405+#ifndef __NR_faccessat2
406+# define __NR_faccessat2 (FLATPAK_MISSING_SYSCALL_BASE + 439)
407+#endif
408+#ifndef __SNR_faccessat2
409+# define __SNR_faccessat2 __NR_faccessat2
410+#endif
411+
412+#ifndef __NR_process_madvise
413+# define __NR_process_madvise (FLATPAK_MISSING_SYSCALL_BASE + 440)
414+#endif
415+#ifndef __SNR_process_madvise
416+# define __SNR_process_madvise __NR_process_madvise
417+#endif
418+
419+#ifndef __NR_epoll_pwait2
420+# define __NR_epoll_pwait2 (FLATPAK_MISSING_SYSCALL_BASE + 441)
421+#endif
422+#ifndef __SNR_epoll_pwait2
423+# define __SNR_epoll_pwait2 __NR_epoll_pwait2
424+#endif
425+
426+#ifndef __NR_mount_setattr
427+# define __NR_mount_setattr (FLATPAK_MISSING_SYSCALL_BASE + 442)
428+#endif
429+#ifndef __SNR_mount_setattr
430+# define __SNR_mount_setattr __NR_mount_setattr
431+#endif
432+
433+#ifndef __NR_quotactl_fd
434+# define __NR_quotactl_fd (FLATPAK_MISSING_SYSCALL_BASE + 443)
435+#endif
436+#ifndef __SNR_quotactl_fd
437+# define __SNR_quotactl_fd __NR_quotactl_fd
438+#endif
439+
440+#ifndef __NR_landlock_create_ruleset
441+# define __NR_landlock_create_ruleset (FLATPAK_MISSING_SYSCALL_BASE + 444)
442+#endif
443+#ifndef __SNR_landlock_create_ruleset
444+# define __SNR_landlock_create_ruleset __NR_landlock_create_ruleset
445+#endif
446+
447+#ifndef __NR_landlock_add_rule
448+# define __NR_landlock_add_rule (FLATPAK_MISSING_SYSCALL_BASE + 445)
449+#endif
450+#ifndef __SNR_landlock_add_rule
451+# define __SNR_landlock_add_rule __NR_landlock_add_rule
452+#endif
453+
454+#ifndef __NR_landlock_restrict_self
455+# define __NR_landlock_restrict_self (FLATPAK_MISSING_SYSCALL_BASE + 446)
456+#endif
457+#ifndef __SNR_landlock_restrict_self
458+# define __SNR_landlock_restrict_self __NR_landlock_restrict_self
459+#endif
460+
461+#ifndef __NR_memfd_secret
462+# define __NR_memfd_secret (FLATPAK_MISSING_SYSCALL_BASE + 447)
463+#endif
464+#ifndef __SNR_memfd_secret
465+# define __SNR_memfd_secret __NR_memfd_secret
466+#endif
467+
468+// Last updated: Linux 5.14, syscall numbers < 448
diff --git a/meta/recipes-sato/webkit/webkitgtk/reproducibility.patch b/meta/recipes-sato/webkit/webkitgtk/reproducibility.patch
new file mode 100644
index 0000000000..e866a1a193
--- /dev/null
+++ b/meta/recipes-sato/webkit/webkitgtk/reproducibility.patch
@@ -0,0 +1,22 @@
1Injection a year based on the current date isn't reproducible. Hack this
2to a specific year for now for reproducibilty and to avoid autobuilder failures.
3
4The correct fix would be to use SOURCE_DATE_EPOCH from the environment and
5then this could be submitted upstream, sadly my ruby isn't up to that.
6
7Upstream-Status: Pending [could be reworked]
8Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
9
10Index: webkitgtk-2.34.2/Source/JavaScriptCore/generator/GeneratedFile.rb
11===================================================================
12--- webkitgtk-2.34.2.orig/Source/JavaScriptCore/generator/GeneratedFile.rb
13+++ webkitgtk-2.34.2/Source/JavaScriptCore/generator/GeneratedFile.rb
14@@ -25,7 +25,7 @@ require 'date'
15 require 'digest'
16
17 $LICENSE = <<-EOF
18-Copyright (C) #{Date.today.year} Apple Inc. All rights reserved.
19+Copyright (C) 2021 Apple Inc. All rights reserved.
20
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions
diff --git a/meta/recipes-sato/webkit/webkitgtk_2.30.5.bb b/meta/recipes-sato/webkit/webkitgtk_2.30.6.bb
index 1fefc75c49..1fdba611ea 100644
--- a/meta/recipes-sato/webkit/webkitgtk_2.30.5.bb
+++ b/meta/recipes-sato/webkit/webkitgtk_2.30.6.bb
@@ -21,9 +21,11 @@ SRC_URI = "https://www.webkitgtk.org/releases/${BPN}-${PV}.tar.xz \
21 file://0001-Extend-atomics-check-to-include-1-byte-CAS-test.patch \ 21 file://0001-Extend-atomics-check-to-include-1-byte-CAS-test.patch \
22 file://musl-lower-stack-usage.patch \ 22 file://musl-lower-stack-usage.patch \
23 file://0001-MiniBrowser-Fix-reproduciblity.patch \ 23 file://0001-MiniBrowser-Fix-reproduciblity.patch \
24 file://reproducibility.patch \
25 file://CVE-2021-42762.patch \
24 " 26 "
25 27
26SRC_URI[sha256sum] = "7d0dab08e3c5ae07bec80b2822ef42e952765d5724cac86eb23999bfed5a7f1f" 28SRC_URI[sha256sum] = "50736ec7a91770b5939d715196e5fe7209b93efcdeef425b24dc51fb8e9d7c1e"
27 29
28inherit cmake pkgconfig gobject-introspection perlnative features_check upstream-version-is-even gtk-doc 30inherit cmake pkgconfig gobject-introspection perlnative features_check upstream-version-is-even gtk-doc
29 31
diff --git a/meta/recipes-support/curl/curl/CVE-2021-22945.patch b/meta/recipes-support/curl/curl/CVE-2021-22945.patch
new file mode 100644
index 0000000000..44c42632ed
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2021-22945.patch
@@ -0,0 +1,35 @@
1From 43157490a5054bd24256fe12876931e8abc9df49 Mon Sep 17 00:00:00 2001
2From: z2_ on hackerone <>
3Date: Tue, 24 Aug 2021 09:50:33 +0200
4Subject: [PATCH] mqtt: clear the leftovers pointer when sending succeeds
5
6CVE-2021-22945
7
8Bug: https://curl.se/docs/CVE-2021-22945.html
9
10Upstream-Status: Backport [https://github.com/curl/curl/commit/43157490a5054bd24256fe12876931e8abc9df49]
11
12Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org>
13
14---
15 lib/mqtt.c | 4 ++++
16 1 file changed, 4 insertions(+)
17
18diff --git a/lib/mqtt.c b/lib/mqtt.c
19index f077e6c3d..fcd40b41e 100644
20--- a/lib/mqtt.c
21+++ b/lib/mqtt.c
22@@ -128,6 +128,10 @@ static CURLcode mqtt_send(struct Curl_easy *data,
23 mq->sendleftovers = sendleftovers;
24 mq->nsend = nsend;
25 }
26+ else {
27+ mq->sendleftovers = NULL;
28+ mq->nsend = 0;
29+ }
30 return result;
31 }
32
33--
342.34.1
35
diff --git a/meta/recipes-support/curl/curl/CVE-2021-22946.patch b/meta/recipes-support/curl/curl/CVE-2021-22946.patch
new file mode 100644
index 0000000000..1cb95f0ea7
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2021-22946.patch
@@ -0,0 +1,333 @@
1From 7c6e072216001fb1280d1868adfdcb54e3372ce7 Mon Sep 17 00:00:00 2001
2From: Patrick Monnerat <patrick@monnerat.net>
3Date: Wed, 8 Sep 2021 11:56:22 +0200
4Subject: [PATCH] ftp,imap,pop3: do not ignore --ssl-reqd
5
6In imap and pop3, check if TLS is required even when capabilities
7request has failed.
8
9In ftp, ignore preauthentication (230 status of server greeting) if TLS
10is required.
11
12Bug: https://curl.se/docs/CVE-2021-22946.html
13
14CVE-2021-22946
15
16Upstream-Status: Backport [https://github.com/curl/curl/commit/364f174724ef115c63d5e5dc1d3342c8a43b1cca]
17
18Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org>
19
20---
21 lib/ftp.c | 9 ++++---
22 lib/imap.c | 24 ++++++++----------
23 lib/pop3.c | 33 +++++++++++-------------
24 tests/data/Makefile.inc | 2 ++
25 tests/data/test984 | 56 +++++++++++++++++++++++++++++++++++++++++
26 tests/data/test985 | 54 +++++++++++++++++++++++++++++++++++++++
27 tests/data/test986 | 53 ++++++++++++++++++++++++++++++++++++++
28 7 files changed, 195 insertions(+), 36 deletions(-)
29 create mode 100644 tests/data/test984
30 create mode 100644 tests/data/test985
31 create mode 100644 tests/data/test986
32
33diff --git a/lib/ftp.c b/lib/ftp.c
34index 3818a9e..8b3fe1d 100644
35--- a/lib/ftp.c
36+++ b/lib/ftp.c
37@@ -2665,9 +2665,12 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
38 /* we have now received a full FTP server response */
39 switch(ftpc->state) {
40 case FTP_WAIT220:
41- if(ftpcode == 230)
42- /* 230 User logged in - already! */
43- return ftp_state_user_resp(data, ftpcode, ftpc->state);
44+ if(ftpcode == 230) {
45+ /* 230 User logged in - already! Take as 220 if TLS required. */
46+ if(data->set.use_ssl <= CURLUSESSL_TRY ||
47+ conn->bits.ftp_use_control_ssl)
48+ return ftp_state_user_resp(data, ftpcode, ftpc->state);
49+ }
50 else if(ftpcode != 220) {
51 failf(data, "Got a %03d ftp-server response when 220 was expected",
52 ftpcode);
53diff --git a/lib/imap.c b/lib/imap.c
54index 2d80699..b056208 100644
55--- a/lib/imap.c
56+++ b/lib/imap.c
57@@ -933,22 +933,18 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data,
58 line += wordlen;
59 }
60 }
61- else if(imapcode == IMAP_RESP_OK) {
62- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
63- /* We don't have a SSL/TLS connection yet, but SSL is requested */
64- if(imapc->tls_supported)
65- /* Switch to TLS connection now */
66- result = imap_perform_starttls(data, conn);
67- else if(data->set.use_ssl == CURLUSESSL_TRY)
68- /* Fallback and carry on with authentication */
69- result = imap_perform_authentication(data, conn);
70- else {
71- failf(data, "STARTTLS not supported.");
72- result = CURLE_USE_SSL_FAILED;
73- }
74+ else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
75+ /* PREAUTH is not compatible with STARTTLS. */
76+ if(imapcode == IMAP_RESP_OK && imapc->tls_supported && !imapc->preauth) {
77+ /* Switch to TLS connection now */
78+ result = imap_perform_starttls(data, conn);
79 }
80- else
81+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
82 result = imap_perform_authentication(data, conn);
83+ else {
84+ failf(data, "STARTTLS not available.");
85+ result = CURLE_USE_SSL_FAILED;
86+ }
87 }
88 else
89 result = imap_perform_authentication(data, conn);
90diff --git a/lib/pop3.c b/lib/pop3.c
91index 0ed3d3e..018fda1 100644
92--- a/lib/pop3.c
93+++ b/lib/pop3.c
94@@ -738,28 +738,23 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code,
95 }
96 }
97 }
98- else if(pop3code == '+') {
99- if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
100- /* We don't have a SSL/TLS connection yet, but SSL is requested */
101- if(pop3c->tls_supported)
102- /* Switch to TLS connection now */
103- result = pop3_perform_starttls(data, conn);
104- else if(data->set.use_ssl == CURLUSESSL_TRY)
105- /* Fallback and carry on with authentication */
106- result = pop3_perform_authentication(data, conn);
107- else {
108- failf(data, "STLS not supported.");
109- result = CURLE_USE_SSL_FAILED;
110- }
111- }
112- else
113- result = pop3_perform_authentication(data, conn);
114- }
115 else {
116 /* Clear text is supported when CAPA isn't recognised */
117- pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
118+ if(pop3code != '+')
119+ pop3c->authtypes |= POP3_TYPE_CLEARTEXT;
120
121- result = pop3_perform_authentication(data, conn);
122+ if(!data->set.use_ssl || conn->ssl[FIRSTSOCKET].use)
123+ result = pop3_perform_authentication(data, conn);
124+ else if(pop3code == '+' && pop3c->tls_supported)
125+ /* Switch to TLS connection now */
126+ result = pop3_perform_starttls(data, conn);
127+ else if(data->set.use_ssl <= CURLUSESSL_TRY)
128+ /* Fallback and carry on with authentication */
129+ result = pop3_perform_authentication(data, conn);
130+ else {
131+ failf(data, "STLS not supported.");
132+ result = CURLE_USE_SSL_FAILED;
133+ }
134 }
135
136 return result;
137diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
138index e08cfc7..e6e2551 100644
139--- a/tests/data/Makefile.inc
140+++ b/tests/data/Makefile.inc
141@@ -115,6 +115,8 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
142 test954 test955 test956 test957 test958 test959 test960 test961 test962 \
143 test963 test964 test965 test966 test967 test968 test969 test970 test971 \
144 \
145+test984 test985 test986 \
146+\
147 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
148 test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
149 test1016 test1017 test1018 test1019 test1020 test1021 test1022 test1023 \
150diff --git a/tests/data/test984 b/tests/data/test984
151new file mode 100644
152index 0000000..e573f23
153--- /dev/null
154+++ b/tests/data/test984
155@@ -0,0 +1,56 @@
156+<testcase>
157+<info>
158+<keywords>
159+IMAP
160+STARTTLS
161+</keywords>
162+</info>
163+
164+#
165+# Server-side
166+<reply>
167+<servercmd>
168+REPLY CAPABILITY A001 BAD Not implemented
169+</servercmd>
170+</reply>
171+
172+#
173+# Client-side
174+<client>
175+<features>
176+SSL
177+</features>
178+<server>
179+imap
180+</server>
181+ <name>
182+IMAP require STARTTLS with failing capabilities
183+ </name>
184+ <command>
185+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl-reqd
186+</command>
187+<file name="log/upload%TESTNUMBER">
188+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
189+From: Fred Foobar <foobar@example.COM>
190+Subject: afternoon meeting
191+To: joe@example.com
192+Message-Id: <B27397-0100000@example.COM>
193+MIME-Version: 1.0
194+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
195+
196+Hello Joe, do you think we can meet at 3:30 tomorrow?
197+</file>
198+</client>
199+
200+#
201+# Verify data after the test has been "shot"
202+<verify>
203+# 64 is CURLE_USE_SSL_FAILED
204+<errorcode>
205+64
206+</errorcode>
207+<protocol>
208+A001 CAPABILITY
209+</protocol>
210+</verify>
211+</testcase>
212diff --git a/tests/data/test985 b/tests/data/test985
213new file mode 100644
214index 0000000..d0db4aa
215--- /dev/null
216+++ b/tests/data/test985
217@@ -0,0 +1,54 @@
218+<testcase>
219+<info>
220+<keywords>
221+POP3
222+STARTTLS
223+</keywords>
224+</info>
225+
226+#
227+# Server-side
228+<reply>
229+<servercmd>
230+REPLY CAPA -ERR Not implemented
231+</servercmd>
232+<data nocheck="yes">
233+From: me@somewhere
234+To: fake@nowhere
235+
236+body
237+
238+--
239+ yours sincerely
240+</data>
241+</reply>
242+
243+#
244+# Client-side
245+<client>
246+<features>
247+SSL
248+</features>
249+<server>
250+pop3
251+</server>
252+ <name>
253+POP3 require STARTTLS with failing capabilities
254+ </name>
255+ <command>
256+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl-reqd
257+ </command>
258+</client>
259+
260+#
261+# Verify data after the test has been "shot"
262+<verify>
263+# 64 is CURLE_USE_SSL_FAILED
264+<errorcode>
265+64
266+</errorcode>
267+<protocol>
268+CAPA
269+</protocol>
270+</verify>
271+</testcase>
272diff --git a/tests/data/test986 b/tests/data/test986
273new file mode 100644
274index 0000000..a709437
275--- /dev/null
276+++ b/tests/data/test986
277@@ -0,0 +1,53 @@
278+<testcase>
279+<info>
280+<keywords>
281+FTP
282+STARTTLS
283+</keywords>
284+</info>
285+
286+#
287+# Server-side
288+<reply>
289+<servercmd>
290+REPLY welcome 230 Welcome
291+REPLY AUTH 500 unknown command
292+</servercmd>
293+</reply>
294+
295+# Client-side
296+<client>
297+<features>
298+SSL
299+</features>
300+<server>
301+ftp
302+</server>
303+ <name>
304+FTP require STARTTLS while preauthenticated
305+ </name>
306+<file name="log/test%TESTNUMBER.txt">
307+data
308+ to
309+ see
310+that FTPS
311+works
312+ so does it?
313+</file>
314+ <command>
315+--ssl-reqd --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret
316+</command>
317+</client>
318+
319+# Verify data after the test has been "shot"
320+<verify>
321+# 64 is CURLE_USE_SSL_FAILED
322+<errorcode>
323+64
324+</errorcode>
325+<protocol>
326+AUTH SSL
327+AUTH TLS
328+</protocol>
329+</verify>
330+</testcase>
331--
3322.34.1
333
diff --git a/meta/recipes-support/curl/curl/CVE-2021-22947.patch b/meta/recipes-support/curl/curl/CVE-2021-22947.patch
new file mode 100644
index 0000000000..9bd9890d72
--- /dev/null
+++ b/meta/recipes-support/curl/curl/CVE-2021-22947.patch
@@ -0,0 +1,357 @@
1From f3f2d2554d09ca0e13039e4915b83faaa55961c4 Mon Sep 17 00:00:00 2001
2From: Patrick Monnerat <patrick@monnerat.net>
3Date: Tue, 7 Sep 2021 13:26:42 +0200
4Subject: [PATCH] ftp,imap,pop3,smtp: reject STARTTLS server response
5
6 pipelining
7
8If a server pipelines future responses within the STARTTLS response, the
9former are preserved in the pingpong cache across TLS negotiation and
10used as responses to the encrypted commands.
11
12This fix detects pipelined STARTTLS responses and rejects them with an
13error.
14
15CVE-2021-22947
16
17Bug: https://curl.se/docs/CVE-2021-22947.html
18
19Upstream-Status: Backport [https://github.com/curl/curl/commit/8ef147c43646e91fdaad5d0e7b60351f842e5c68]
20
21Signed-off-by: Robert Joslyn <robert.joslyn@redrectangle.org>
22
23---
24 lib/ftp.c | 3 +++
25 lib/imap.c | 4 +++
26 lib/pop3.c | 4 +++
27 lib/smtp.c | 4 +++
28 tests/data/Makefile.inc | 2 +-
29 tests/data/test980 | 52 ++++++++++++++++++++++++++++++++++++
30 tests/data/test981 | 59 +++++++++++++++++++++++++++++++++++++++++
31 tests/data/test982 | 57 +++++++++++++++++++++++++++++++++++++++
32 tests/data/test983 | 52 ++++++++++++++++++++++++++++++++++++
33 9 files changed, 236 insertions(+), 1 deletion(-)
34 create mode 100644 tests/data/test980
35 create mode 100644 tests/data/test981
36 create mode 100644 tests/data/test982
37 create mode 100644 tests/data/test983
38
39diff --git a/lib/ftp.c b/lib/ftp.c
40index 8b3fe1d..a55566a 100644
41--- a/lib/ftp.c
42+++ b/lib/ftp.c
43@@ -2727,6 +2727,9 @@ static CURLcode ftp_statemachine(struct Curl_easy *data,
44 case FTP_AUTH:
45 /* we have gotten the response to a previous AUTH command */
46
47+ if(pp->cache_size)
48+ return CURLE_WEIRD_SERVER_REPLY; /* Forbid pipelining in response. */
49+
50 /* RFC2228 (page 5) says:
51 *
52 * If the server is willing to accept the named security mechanism,
53diff --git a/lib/imap.c b/lib/imap.c
54index b056208..9230f17 100644
55--- a/lib/imap.c
56+++ b/lib/imap.c
57@@ -962,6 +962,10 @@ static CURLcode imap_state_starttls_resp(struct Curl_easy *data,
58
59 (void)instate; /* no use for this yet */
60
61+ /* Pipelining in response is forbidden. */
62+ if(data->conn->proto.imapc.pp.cache_size)
63+ return CURLE_WEIRD_SERVER_REPLY;
64+
65 if(imapcode != IMAP_RESP_OK) {
66 if(data->set.use_ssl != CURLUSESSL_TRY) {
67 failf(data, "STARTTLS denied");
68diff --git a/lib/pop3.c b/lib/pop3.c
69index 018fda1..4f953f7 100644
70--- a/lib/pop3.c
71+++ b/lib/pop3.c
72@@ -769,6 +769,10 @@ static CURLcode pop3_state_starttls_resp(struct Curl_easy *data,
73 CURLcode result = CURLE_OK;
74 (void)instate; /* no use for this yet */
75
76+ /* Pipelining in response is forbidden. */
77+ if(data->conn->proto.pop3c.pp.cache_size)
78+ return CURLE_WEIRD_SERVER_REPLY;
79+
80 if(pop3code != '+') {
81 if(data->set.use_ssl != CURLUSESSL_TRY) {
82 failf(data, "STARTTLS denied");
83diff --git a/lib/smtp.c b/lib/smtp.c
84index 1fc8800..51445f6 100644
85--- a/lib/smtp.c
86+++ b/lib/smtp.c
87@@ -832,6 +832,10 @@ static CURLcode smtp_state_starttls_resp(struct Curl_easy *data,
88 CURLcode result = CURLE_OK;
89 (void)instate; /* no use for this yet */
90
91+ /* Pipelining in response is forbidden. */
92+ if(data->conn->proto.smtpc.pp.cache_size)
93+ return CURLE_WEIRD_SERVER_REPLY;
94+
95 if(smtpcode != 220) {
96 if(data->set.use_ssl != CURLUSESSL_TRY) {
97 failf(data, "STARTTLS denied, code %d", smtpcode);
98diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
99index e6e2551..22d7a0b 100644
100--- a/tests/data/Makefile.inc
101+++ b/tests/data/Makefile.inc
102@@ -115,7 +115,7 @@ test945 test946 test947 test948 test949 test950 test951 test952 test953 \
103 test954 test955 test956 test957 test958 test959 test960 test961 test962 \
104 test963 test964 test965 test966 test967 test968 test969 test970 test971 \
105 \
106-test984 test985 test986 \
107+test980 test981 test982 test983 test984 test985 test986 \
108 \
109 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 \
110 test1008 test1009 test1010 test1011 test1012 test1013 test1014 test1015 \
111diff --git a/tests/data/test980 b/tests/data/test980
112new file mode 100644
113index 0000000..97567f8
114--- /dev/null
115+++ b/tests/data/test980
116@@ -0,0 +1,52 @@
117+<testcase>
118+<info>
119+<keywords>
120+SMTP
121+STARTTLS
122+</keywords>
123+</info>
124+
125+#
126+# Server-side
127+<reply>
128+<servercmd>
129+CAPA STARTTLS
130+AUTH PLAIN
131+REPLY STARTTLS 454 currently unavailable\r\n235 Authenticated\r\n250 2.1.0 Sender ok\r\n250 2.1.5 Recipient ok\r\n354 Enter mail\r\n250 2.0.0 Accepted
132+REPLY AUTH 535 5.7.8 Authentication credentials invalid
133+</servercmd>
134+</reply>
135+
136+#
137+# Client-side
138+<client>
139+<features>
140+SSL
141+</features>
142+<server>
143+smtp
144+</server>
145+ <name>
146+SMTP STARTTLS pipelined server response
147+ </name>
148+<stdin>
149+mail body
150+</stdin>
151+ <command>
152+smtp://%HOSTIP:%SMTPPORT/%TESTNUMBER --mail-rcpt recipient@example.com --mail-from sender@example.com -u user:secret --ssl --sasl-ir -T -
153+</command>
154+</client>
155+
156+#
157+# Verify data after the test has been "shot"
158+<verify>
159+# 8 is CURLE_WEIRD_SERVER_REPLY
160+<errorcode>
161+8
162+</errorcode>
163+<protocol>
164+EHLO %TESTNUMBER
165+STARTTLS
166+</protocol>
167+</verify>
168+</testcase>
169diff --git a/tests/data/test981 b/tests/data/test981
170new file mode 100644
171index 0000000..2b98ce4
172--- /dev/null
173+++ b/tests/data/test981
174@@ -0,0 +1,59 @@
175+<testcase>
176+<info>
177+<keywords>
178+IMAP
179+STARTTLS
180+</keywords>
181+</info>
182+
183+#
184+# Server-side
185+<reply>
186+<servercmd>
187+CAPA STARTTLS
188+REPLY STARTTLS A002 BAD currently unavailable\r\nA003 OK Authenticated\r\nA004 OK Accepted
189+REPLY LOGIN A003 BAD Authentication credentials invalid
190+</servercmd>
191+</reply>
192+
193+#
194+# Client-side
195+<client>
196+<features>
197+SSL
198+</features>
199+<server>
200+imap
201+</server>
202+ <name>
203+IMAP STARTTLS pipelined server response
204+ </name>
205+ <command>
206+imap://%HOSTIP:%IMAPPORT/%TESTNUMBER -T log/upload%TESTNUMBER -u user:secret --ssl
207+</command>
208+<file name="log/upload%TESTNUMBER">
209+Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
210+From: Fred Foobar <foobar@example.COM>
211+Subject: afternoon meeting
212+To: joe@example.com
213+Message-Id: <B27397-0100000@example.COM>
214+MIME-Version: 1.0
215+Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
216+
217+Hello Joe, do you think we can meet at 3:30 tomorrow?
218+</file>
219+</client>
220+
221+#
222+# Verify data after the test has been "shot"
223+<verify>
224+# 8 is CURLE_WEIRD_SERVER_REPLY
225+<errorcode>
226+8
227+</errorcode>
228+<protocol>
229+A001 CAPABILITY
230+A002 STARTTLS
231+</protocol>
232+</verify>
233+</testcase>
234diff --git a/tests/data/test982 b/tests/data/test982
235new file mode 100644
236index 0000000..9e07cc0
237--- /dev/null
238+++ b/tests/data/test982
239@@ -0,0 +1,57 @@
240+<testcase>
241+<info>
242+<keywords>
243+POP3
244+STARTTLS
245+</keywords>
246+</info>
247+
248+#
249+# Server-side
250+<reply>
251+<servercmd>
252+CAPA STLS USER
253+REPLY STLS -ERR currently unavailable\r\n+OK user accepted\r\n+OK authenticated
254+REPLY PASS -ERR Authentication credentials invalid
255+</servercmd>
256+<data nocheck="yes">
257+From: me@somewhere
258+To: fake@nowhere
259+
260+body
261+
262+--
263+ yours sincerely
264+</data>
265+</reply>
266+
267+#
268+# Client-side
269+<client>
270+<features>
271+SSL
272+</features>
273+<server>
274+pop3
275+</server>
276+ <name>
277+POP3 STARTTLS pipelined server response
278+ </name>
279+ <command>
280+pop3://%HOSTIP:%POP3PORT/%TESTNUMBER -u user:secret --ssl
281+ </command>
282+</client>
283+
284+#
285+# Verify data after the test has been "shot"
286+<verify>
287+# 8 is CURLE_WEIRD_SERVER_REPLY
288+<errorcode>
289+8
290+</errorcode>
291+<protocol>
292+CAPA
293+STLS
294+</protocol>
295+</verify>
296+</testcase>
297diff --git a/tests/data/test983 b/tests/data/test983
298new file mode 100644
299index 0000000..300ec45
300--- /dev/null
301+++ b/tests/data/test983
302@@ -0,0 +1,52 @@
303+<testcase>
304+<info>
305+<keywords>
306+FTP
307+STARTTLS
308+</keywords>
309+</info>
310+
311+#
312+# Server-side
313+<reply>
314+<servercmd>
315+REPLY AUTH 500 unknown command\r\n500 unknown command\r\n331 give password\r\n230 Authenticated\r\n257 "/"\r\n200 OK\r\n200 OK\r\n200 OK\r\n226 Transfer complete
316+REPLY PASS 530 Login incorrect
317+</servercmd>
318+</reply>
319+
320+# Client-side
321+<client>
322+<features>
323+SSL
324+</features>
325+<server>
326+ftp
327+</server>
328+ <name>
329+FTP STARTTLS pipelined server response
330+ </name>
331+<file name="log/test%TESTNUMBER.txt">
332+data
333+ to
334+ see
335+that FTPS
336+works
337+ so does it?
338+</file>
339+ <command>
340+--ssl --ftp-ssl-control ftp://%HOSTIP:%FTPPORT/%TESTNUMBER -T log/test%TESTNUMBER.txt -u user:secret -P %CLIENTIP
341+</command>
342+</client>
343+
344+# Verify data after the test has been "shot"
345+<verify>
346+# 8 is CURLE_WEIRD_SERVER_REPLY
347+<errorcode>
348+8
349+</errorcode>
350+<protocol>
351+AUTH SSL
352+</protocol>
353+</verify>
354+</testcase>
355--
3562.34.1
357
diff --git a/meta/recipes-support/curl/curl_7.75.0.bb b/meta/recipes-support/curl/curl_7.75.0.bb
index d64e5e1f79..accede604c 100644
--- a/meta/recipes-support/curl/curl_7.75.0.bb
+++ b/meta/recipes-support/curl/curl_7.75.0.bb
@@ -21,6 +21,9 @@ SRC_URI = "https://curl.haxx.se/download/curl-${PV}.tar.bz2 \
21 file://CVE-2021-22901.patch \ 21 file://CVE-2021-22901.patch \
22 file://CVE-2021-22924.patch \ 22 file://CVE-2021-22924.patch \
23 file://CVE-2021-22926.patch \ 23 file://CVE-2021-22926.patch \
24 file://CVE-2021-22945.patch \
25 file://CVE-2021-22946.patch \
26 file://CVE-2021-22947.patch \
24" 27"
25 28
26SRC_URI[sha256sum] = "50552d4501c178e4cc68baaecc487f466a3d6d19bbf4e50a01869effb316d026" 29SRC_URI[sha256sum] = "50552d4501c178e4cc68baaecc487f466a3d6d19bbf4e50a01869effb316d026"
@@ -28,6 +31,10 @@ SRC_URI[sha256sum] = "50552d4501c178e4cc68baaecc487f466a3d6d19bbf4e50a01869effb3
28# Curl has used many names over the years... 31# Curl has used many names over the years...
29CVE_PRODUCT = "haxx:curl haxx:libcurl curl:curl curl:libcurl libcurl:libcurl daniel_stenberg:curl" 32CVE_PRODUCT = "haxx:curl haxx:libcurl curl:curl curl:libcurl libcurl:libcurl daniel_stenberg:curl"
30 33
34# These only apply when using --with-libmetalink, but --without-libmetalink is
35# set below.
36CVE_CHECK_WHITELIST += "CVE-2021-22922 CVE-2021-22923"
37
31inherit autotools pkgconfig binconfig multilib_header 38inherit autotools pkgconfig binconfig multilib_header
32 39
33PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)} gnutls libidn proxy threaded-resolver verbose zlib" 40PACKAGECONFIG ??= "${@bb.utils.filter('DISTRO_FEATURES', 'ipv6', d)} gnutls libidn proxy threaded-resolver verbose zlib"
@@ -65,6 +72,7 @@ PACKAGECONFIG[threaded-resolver] = "--enable-threaded-resolver,--disable-threade
65PACKAGECONFIG[verbose] = "--enable-verbose,--disable-verbose" 72PACKAGECONFIG[verbose] = "--enable-verbose,--disable-verbose"
66PACKAGECONFIG[zlib] = "--with-zlib=${STAGING_LIBDIR}/../,--without-zlib,zlib" 73PACKAGECONFIG[zlib] = "--with-zlib=${STAGING_LIBDIR}/../,--without-zlib,zlib"
67 74
75# Keep --without-libmetalink to mitigate CVE-2021-22922 and CVE-2021-22923
68EXTRA_OECONF = " \ 76EXTRA_OECONF = " \
69 --disable-libcurl-option \ 77 --disable-libcurl-option \
70 --disable-ntlm-wb \ 78 --disable-ntlm-wb \
diff --git a/meta/recipes-support/gmp/gmp/cve-2021-43618.patch b/meta/recipes-support/gmp/gmp/cve-2021-43618.patch
new file mode 100644
index 0000000000..095fb21eaa
--- /dev/null
+++ b/meta/recipes-support/gmp/gmp/cve-2021-43618.patch
@@ -0,0 +1,27 @@
1CVE: CVE-2021-43618
2Upstream-Status: Backport
3Signed-off-by: Ross Burton <ross.burton@arm.com>
4
5# HG changeset patch
6# User Marco Bodrato <bodrato@mail.dm.unipi.it>
7# Date 1634836009 -7200
8# Node ID 561a9c25298e17bb01896801ff353546c6923dbd
9# Parent e1fd9db13b475209a864577237ea4b9105b3e96e
10mpz/inp_raw.c: Avoid bit size overflows
11
12diff -r e1fd9db13b47 -r 561a9c25298e mpz/inp_raw.c
13--- a/mpz/inp_raw.c Tue Dec 22 23:49:51 2020 +0100
14+++ b/mpz/inp_raw.c Thu Oct 21 19:06:49 2021 +0200
15@@ -88,8 +88,11 @@
16
17 abs_csize = ABS (csize);
18
19+ if (UNLIKELY (abs_csize > ~(mp_bitcnt_t) 0 / 8))
20+ return 0; /* Bit size overflows */
21+
22 /* round up to a multiple of limbs */
23- abs_xsize = BITS_TO_LIMBS (abs_csize*8);
24+ abs_xsize = BITS_TO_LIMBS ((mp_bitcnt_t) abs_csize * 8);
25
26 if (abs_xsize != 0)
27 {
diff --git a/meta/recipes-support/gmp/gmp_6.2.1.bb b/meta/recipes-support/gmp/gmp_6.2.1.bb
index 3c50f928ab..f97c588c31 100644
--- a/meta/recipes-support/gmp/gmp_6.2.1.bb
+++ b/meta/recipes-support/gmp/gmp_6.2.1.bb
@@ -12,6 +12,7 @@ SRC_URI = "https://gmplib.org/download/${BPN}/${BP}${REVISION}.tar.bz2 \
12 file://use-includedir.patch \ 12 file://use-includedir.patch \
13 file://0001-Append-the-user-provided-flags-to-the-auto-detected-.patch \ 13 file://0001-Append-the-user-provided-flags-to-the-auto-detected-.patch \
14 file://0001-confiure.ac-Believe-the-cflags-from-environment.patch \ 14 file://0001-confiure.ac-Believe-the-cflags-from-environment.patch \
15 file://cve-2021-43618.patch \
15 " 16 "
16SRC_URI[md5sum] = "28971fc21cf028042d4897f02fd355ea" 17SRC_URI[md5sum] = "28971fc21cf028042d4897f02fd355ea"
17SRC_URI[sha256sum] = "eae9326beb4158c386e39a356818031bd28f3124cf915f8c5b1dc4c7a36b4d7c" 18SRC_URI[sha256sum] = "eae9326beb4158c386e39a356818031bd28f3124cf915f8c5b1dc4c7a36b4d7c"
diff --git a/meta/recipes-support/libgcrypt/libgcrypt_1.9.3.bb b/meta/recipes-support/libgcrypt/libgcrypt_1.9.4.bb
index fd3d8e09f2..c212d02651 100644
--- a/meta/recipes-support/libgcrypt/libgcrypt_1.9.3.bb
+++ b/meta/recipes-support/libgcrypt/libgcrypt_1.9.4.bb
@@ -27,7 +27,7 @@ SRC_URI = "${GNUPG_MIRROR}/libgcrypt/libgcrypt-${PV}.tar.bz2 \
27 file://0004-tests-Makefile.am-fix-undefined-reference-to-pthread.patch \ 27 file://0004-tests-Makefile.am-fix-undefined-reference-to-pthread.patch \
28 file://0001-Makefile.am-add-a-missing-space.patch \ 28 file://0001-Makefile.am-add-a-missing-space.patch \
29 " 29 "
30SRC_URI[sha256sum] = "97ebe4f94e2f7e35b752194ce15a0f3c66324e0ff6af26659bbfb5ff2ec328fd" 30SRC_URI[sha256sum] = "ea849c83a72454e3ed4267697e8ca03390aee972ab421e7df69dfe42b65caaf7"
31 31
32# Below whitelisted CVEs are disputed and not affecting crypto libraries for any distro. 32# Below whitelisted CVEs are disputed and not affecting crypto libraries for any distro.
33CVE_CHECK_WHITELIST += "CVE-2018-12433 CVE-2018-12438" 33CVE_CHECK_WHITELIST += "CVE-2018-12433 CVE-2018-12438"
diff --git a/meta/recipes-support/libpcre/libpcre2_10.36.bb b/meta/recipes-support/libpcre/libpcre2_10.36.bb
index d8077a1224..d64822be30 100644
--- a/meta/recipes-support/libpcre/libpcre2_10.36.bb
+++ b/meta/recipes-support/libpcre/libpcre2_10.36.bb
@@ -10,7 +10,9 @@ SECTION = "devel"
10LICENSE = "BSD-3-Clause" 10LICENSE = "BSD-3-Clause"
11LIC_FILES_CHKSUM = "file://LICENCE;md5=60c08fab1357bfe9084b333bc33362d6" 11LIC_FILES_CHKSUM = "file://LICENCE;md5=60c08fab1357bfe9084b333bc33362d6"
12 12
13SRC_URI = "https://ftp.pcre.org/pub/pcre/pcre2-${PV}.tar.bz2" 13SRC_URI = "https://github.com/PhilipHazel/pcre2/releases/download/pcre2-${PV}/pcre2-${PV}.tar.bz2"
14
15UPSTREAM_CHECK_URI = "https://github.com/PhilipHazel/pcre2/releases"
14 16
15SRC_URI[sha256sum] = "a9ef39278113542968c7c73a31cfcb81aca1faa64690f400b907e8ab6b4a665c" 17SRC_URI[sha256sum] = "a9ef39278113542968c7c73a31cfcb81aca1faa64690f400b907e8ab6b4a665c"
16 18
diff --git a/meta/recipes-support/libpcre/libpcre_8.44.bb b/meta/recipes-support/libpcre/libpcre_8.44.bb
index cd80dc7345..3267c5ad72 100644
--- a/meta/recipes-support/libpcre/libpcre_8.44.bb
+++ b/meta/recipes-support/libpcre/libpcre_8.44.bb
@@ -7,7 +7,7 @@ HOMEPAGE = "http://www.pcre.org"
7SECTION = "devel" 7SECTION = "devel"
8LICENSE = "BSD-3-Clause" 8LICENSE = "BSD-3-Clause"
9LIC_FILES_CHKSUM = "file://LICENCE;md5=3bb381a66a5385b246d4877922e7511e" 9LIC_FILES_CHKSUM = "file://LICENCE;md5=3bb381a66a5385b246d4877922e7511e"
10SRC_URI = "https://ftp.pcre.org/pub/pcre/pcre-${PV}.tar.bz2 \ 10SRC_URI = "${SOURCEFORGE_MIRROR}/pcre/pcre-${PV}.tar.bz2 \
11 file://run-ptest \ 11 file://run-ptest \
12 file://Makefile \ 12 file://Makefile \
13 " 13 "
diff --git a/meta/recipes-support/libusb/libusb1_1.0.24.bb b/meta/recipes-support/libusb/libusb1_1.0.24.bb
index 92e66b1b16..76a707b70f 100644
--- a/meta/recipes-support/libusb/libusb1_1.0.24.bb
+++ b/meta/recipes-support/libusb/libusb1_1.0.24.bb
@@ -1,7 +1,7 @@
1SUMMARY = "Userspace library to access USB (version 1.0)" 1SUMMARY = "Userspace library to access USB (version 1.0)"
2DESCRIPTION = "A cross-platform library to access USB devices from Linux, \ 2DESCRIPTION = "A cross-platform library to access USB devices from Linux, \
3macOS, Windows, OpenBSD/NetBSD, Haiku and Solaris userspace." 3macOS, Windows, OpenBSD/NetBSD, Haiku and Solaris userspace."
4HOMEPAGE = "http://libusb.sf.net" 4HOMEPAGE = "https://libusb.info"
5BUGTRACKER = "http://www.libusb.org/report" 5BUGTRACKER = "http://www.libusb.org/report"
6SECTION = "libs" 6SECTION = "libs"
7 7
@@ -10,10 +10,12 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=fbc093901857fcd118f065f900982c24"
10 10
11BBCLASSEXTEND = "native nativesdk" 11BBCLASSEXTEND = "native nativesdk"
12 12
13SRC_URI = "${SOURCEFORGE_MIRROR}/libusb/libusb-${PV}.tar.bz2 \ 13SRC_URI = "https://github.com/libusb/libusb/releases/download/v${PV}/libusb-${PV}.tar.bz2 \
14 file://run-ptest \ 14 file://run-ptest \
15 " 15 "
16 16
17UPSTREAM_CHECK_URI = "https://github.com/libusb/libusb/releases"
18
17SRC_URI[sha256sum] = "7efd2685f7b327326dcfb85cee426d9b871fd70e22caa15bb68d595ce2a2b12a" 19SRC_URI[sha256sum] = "7efd2685f7b327326dcfb85cee426d9b871fd70e22caa15bb68d595ce2a2b12a"
18 20
19S = "${WORKDIR}/libusb-${PV}" 21S = "${WORKDIR}/libusb-${PV}"
diff --git a/meta/recipes-support/vim/files/0001-src-Makefile-improve-reproducibility.patch b/meta/recipes-support/vim/files/0001-src-Makefile-improve-reproducibility.patch
index 63a7b78f12..2fc11dbdc2 100644
--- a/meta/recipes-support/vim/files/0001-src-Makefile-improve-reproducibility.patch
+++ b/meta/recipes-support/vim/files/0001-src-Makefile-improve-reproducibility.patch
@@ -16,11 +16,11 @@ Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
16 src/Makefile | 14 ++++---------- 16 src/Makefile | 14 ++++----------
17 1 file changed, 4 insertions(+), 10 deletions(-) 17 1 file changed, 4 insertions(+), 10 deletions(-)
18 18
19diff --git a/src/Makefile b/src/Makefile 19Index: git/src/Makefile
20index f2fafa4dc..7148d4bd9 100644 20===================================================================
21--- a/src/Makefile 21--- git.orig/src/Makefile
22+++ b/src/Makefile 22+++ git/src/Makefile
23@@ -2845,16 +2845,10 @@ auto/pathdef.c: Makefile auto/config.mk 23@@ -3101,16 +3101,10 @@ auto/pathdef.c: Makefile auto/config.mk
24 -@echo '#include "vim.h"' >> $@ 24 -@echo '#include "vim.h"' >> $@
25 -@echo 'char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)";' | $(QUOTESED) >> $@ 25 -@echo 'char_u *default_vim_dir = (char_u *)"$(VIMRCLOC)";' | $(QUOTESED) >> $@
26 -@echo 'char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)";' | $(QUOTESED) >> $@ 26 -@echo 'char_u *default_vimruntime_dir = (char_u *)"$(VIMRUNTIMEDIR)";' | $(QUOTESED) >> $@
@@ -41,6 +41,3 @@ index f2fafa4dc..7148d4bd9 100644
41 -@sh $(srcdir)/pathdef.sh 41 -@sh $(srcdir)/pathdef.sh
42 42
43 GUI_GTK_RES_INPUTS = \ 43 GUI_GTK_RES_INPUTS = \
44--
452.17.1
46
diff --git a/meta/recipes-support/vim/files/CVE-2021-3778.patch b/meta/recipes-support/vim/files/CVE-2021-3778.patch
deleted file mode 100644
index 04ac413e56..0000000000
--- a/meta/recipes-support/vim/files/CVE-2021-3778.patch
+++ /dev/null
@@ -1,34 +0,0 @@
1From 9ba62f1042513fcadcc4e8fdcee171db66ef1d69 Mon Sep 17 00:00:00 2001
2From: Bram Moolenaar <Bram@vim.org>
3Date: Fri, 24 Sep 2021 15:15:24 +0800
4Subject: [PATCH] patch 8.2.3409: reading beyond end of line with invalid utf-8
5 character
6
7Problem: Reading beyond end of line with invalid utf-8 character.
8Solution: Check for NUL when advancing.
9
10Upstream-Status: Backport [https://github.com/vim/vim/commit/65b605665997fad54ef39a93199e305af2fe4d7f]
11CVE: CVE-2021-3778
12
13Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
14---
15 src/regexp_nfa.c | 3 ++-
16 1 file changed, 2 insertions(+), 1 deletion(-)
17
18diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
19index fb512f961..2806408de 100644
20--- a/src/regexp_nfa.c
21+++ b/src/regexp_nfa.c
22@@ -5455,7 +5455,8 @@ find_match_text(colnr_T startcol, int regstart, char_u *match_text)
23 match = FALSE;
24 break;
25 }
26- len2 += MB_CHAR2LEN(c2);
27+ len2 += enc_utf8 ? utf_ptr2len(rex.line + col + len2)
28+ : MB_CHAR2LEN(c2);
29 }
30 if (match
31 // check that no composing char follows
32--
332.17.1
34
diff --git a/meta/recipes-support/vim/files/CVE-2021-3872.patch b/meta/recipes-support/vim/files/CVE-2021-3872.patch
deleted file mode 100644
index f0f30933fa..0000000000
--- a/meta/recipes-support/vim/files/CVE-2021-3872.patch
+++ /dev/null
@@ -1,57 +0,0 @@
1From 132d060ffbb9651f0d79bd0b6d80cab460235a99 Mon Sep 17 00:00:00 2001
2From: Bram Moolenaar <Bram@vim.org>
3Date: Fri, 12 Nov 2021 02:56:51 +0000
4Subject: [PATCH] patch 8.2.3487: illegal memory access if buffer name is very
5 long
6
7Problem: Illegal memory access if buffer name is very long.
8Solution: Make sure not to go over the end of the buffer.
9
10CVE: CVE-2021-3872
11
12Upstream-Status: Backport [https://github.com/vim/vim/commit/826bfe4bbd7594188e3d74d2539d9707b1c6a14b]
13
14Signed-off-by: Mingli Yu <mingli.yu@windriver.com>
15---
16 src/drawscreen.c | 10 +++++-----
17 1 file changed, 5 insertions(+), 5 deletions(-)
18
19diff --git a/src/drawscreen.c b/src/drawscreen.c
20index 3a88ee979..9acb70552 100644
21--- a/src/drawscreen.c
22+++ b/src/drawscreen.c
23@@ -446,13 +446,13 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
24 *(p + len++) = ' ';
25 if (bt_help(wp->w_buffer))
26 {
27- STRCPY(p + len, _("[Help]"));
28+ vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Help]"));
29 len += (int)STRLEN(p + len);
30 }
31 #ifdef FEAT_QUICKFIX
32 if (wp->w_p_pvw)
33 {
34- STRCPY(p + len, _("[Preview]"));
35+ vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Preview]"));
36 len += (int)STRLEN(p + len);
37 }
38 #endif
39@@ -462,12 +462,12 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED)
40 #endif
41 )
42 {
43- STRCPY(p + len, "[+]");
44- len += 3;
45+ vim_snprintf((char *)p + len, MAXPATHL - len, "%s", "[+]");
46+ len += (int)STRLEN(p + len);
47 }
48 if (wp->w_buffer->b_p_ro)
49 {
50- STRCPY(p + len, _("[RO]"));
51+ vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[RO]"));
52 len += (int)STRLEN(p + len);
53 }
54
55--
562.31.1
57
diff --git a/meta/recipes-support/vim/files/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9.patch b/meta/recipes-support/vim/files/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9.patch
deleted file mode 100644
index 1cee759502..0000000000
--- a/meta/recipes-support/vim/files/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9.patch
+++ /dev/null
@@ -1,207 +0,0 @@
1From b7081e135a16091c93f6f5f7525a5c58fb7ca9f9 Mon Sep 17 00:00:00 2001
2From: Bram Moolenaar <Bram@vim.org>
3Date: Sat, 4 Sep 2021 18:47:28 +0200
4Subject: [PATCH] patch 8.2.3402: invalid memory access when using :retab with
5 large value
6
7Problem: Invalid memory access when using :retab with large value.
8Solution: Check the number is positive.
9
10CVE: CVE-2021-3770
11Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
12Upstream-Status: Backport [https://github.com/vim/vim/commit/b7081e135a16091c93f6f5f7525a5c58fb7ca9f9]
13---
14 src/indent.c | 34 +++++++++++++++++++++-------------
15 src/option.c | 12 ++++++------
16 src/optionstr.c | 4 ++--
17 src/testdir/test_retab.vim | 3 +++
18 src/version.c | 2 ++
19 5 files changed, 34 insertions(+), 21 deletions(-)
20
21Index: git/src/indent.c
22===================================================================
23--- git.orig/src/indent.c
24+++ git/src/indent.c
25@@ -18,18 +18,19 @@
26 /*
27 * Set the integer values corresponding to the string setting of 'vartabstop'.
28 * "array" will be set, caller must free it if needed.
29+ * Return FAIL for an error.
30 */
31 int
32 tabstop_set(char_u *var, int **array)
33 {
34- int valcount = 1;
35- int t;
36- char_u *cp;
37+ int valcount = 1;
38+ int t;
39+ char_u *cp;
40
41 if (var[0] == NUL || (var[0] == '0' && var[1] == NUL))
42 {
43 *array = NULL;
44- return TRUE;
45+ return OK;
46 }
47
48 for (cp = var; *cp != NUL; ++cp)
49@@ -43,8 +44,8 @@ tabstop_set(char_u *var, int **array)
50 if (cp != end)
51 emsg(_(e_positive));
52 else
53- emsg(_(e_invarg));
54- return FALSE;
55+ semsg(_(e_invarg2), cp);
56+ return FAIL;
57 }
58 }
59
60@@ -55,26 +56,33 @@ tabstop_set(char_u *var, int **array)
61 ++valcount;
62 continue;
63 }
64- emsg(_(e_invarg));
65- return FALSE;
66+ semsg(_(e_invarg2), var);
67+ return FAIL;
68 }
69
70 *array = ALLOC_MULT(int, valcount + 1);
71 if (*array == NULL)
72- return FALSE;
73+ return FAIL;
74 (*array)[0] = valcount;
75
76 t = 1;
77 for (cp = var; *cp != NUL;)
78 {
79- (*array)[t++] = atoi((char *)cp);
80- while (*cp != NUL && *cp != ',')
81+ int n = atoi((char *)cp);
82+
83+ if (n < 0 || n > 9999)
84+ {
85+ semsg(_(e_invarg2), cp);
86+ return FAIL;
87+ }
88+ (*array)[t++] = n;
89+ while (*cp != NUL && *cp != ',')
90 ++cp;
91 if (*cp != NUL)
92 ++cp;
93 }
94
95- return TRUE;
96+ return OK;
97 }
98
99 /*
100@@ -1556,7 +1564,7 @@ ex_retab(exarg_T *eap)
101
102 #ifdef FEAT_VARTABS
103 new_ts_str = eap->arg;
104- if (!tabstop_set(eap->arg, &new_vts_array))
105+ if (tabstop_set(eap->arg, &new_vts_array) == FAIL)
106 return;
107 while (vim_isdigit(*(eap->arg)) || *(eap->arg) == ',')
108 ++(eap->arg);
109Index: git/src/option.c
110===================================================================
111--- git.orig/src/option.c
112+++ git/src/option.c
113@@ -2292,9 +2292,9 @@ didset_options2(void)
114 #endif
115 #ifdef FEAT_VARTABS
116 vim_free(curbuf->b_p_vsts_array);
117- tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
118+ (void)tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
119 vim_free(curbuf->b_p_vts_array);
120- tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
121+ (void)tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
122 #endif
123 }
124
125@@ -5756,7 +5756,7 @@ buf_copy_options(buf_T *buf, int flags)
126 buf->b_p_vsts = vim_strsave(p_vsts);
127 COPY_OPT_SCTX(buf, BV_VSTS);
128 if (p_vsts && p_vsts != empty_option)
129- tabstop_set(p_vsts, &buf->b_p_vsts_array);
130+ (void)tabstop_set(p_vsts, &buf->b_p_vsts_array);
131 else
132 buf->b_p_vsts_array = 0;
133 buf->b_p_vsts_nopaste = p_vsts_nopaste
134@@ -5914,7 +5914,7 @@ buf_copy_options(buf_T *buf, int flags)
135 buf->b_p_isk = save_p_isk;
136 #ifdef FEAT_VARTABS
137 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
138- tabstop_set(p_vts, &buf->b_p_vts_array);
139+ (void)tabstop_set(p_vts, &buf->b_p_vts_array);
140 else
141 buf->b_p_vts_array = NULL;
142 #endif
143@@ -5929,7 +5929,7 @@ buf_copy_options(buf_T *buf, int flags)
144 buf->b_p_vts = vim_strsave(p_vts);
145 COPY_OPT_SCTX(buf, BV_VTS);
146 if (p_vts && p_vts != empty_option && !buf->b_p_vts_array)
147- tabstop_set(p_vts, &buf->b_p_vts_array);
148+ (void)tabstop_set(p_vts, &buf->b_p_vts_array);
149 else
150 buf->b_p_vts_array = NULL;
151 #endif
152@@ -6634,7 +6634,7 @@ paste_option_changed(void)
153 if (buf->b_p_vsts_array)
154 vim_free(buf->b_p_vsts_array);
155 if (buf->b_p_vsts && buf->b_p_vsts != empty_option)
156- tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
157+ (void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
158 else
159 buf->b_p_vsts_array = 0;
160 #endif
161Index: git/src/optionstr.c
162===================================================================
163--- git.orig/src/optionstr.c
164+++ git/src/optionstr.c
165@@ -2166,7 +2166,7 @@ did_set_string_option(
166 if (errmsg == NULL)
167 {
168 int *oldarray = curbuf->b_p_vsts_array;
169- if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)))
170+ if (tabstop_set(*varp, &(curbuf->b_p_vsts_array)) == OK)
171 {
172 if (oldarray)
173 vim_free(oldarray);
174@@ -2205,7 +2205,7 @@ did_set_string_option(
175 {
176 int *oldarray = curbuf->b_p_vts_array;
177
178- if (tabstop_set(*varp, &(curbuf->b_p_vts_array)))
179+ if (tabstop_set(*varp, &(curbuf->b_p_vts_array)) == OK)
180 {
181 vim_free(oldarray);
182 #ifdef FEAT_FOLDING
183Index: git/src/testdir/test_retab.vim
184===================================================================
185--- git.orig/src/testdir/test_retab.vim
186+++ git/src/testdir/test_retab.vim
187@@ -74,4 +74,7 @@ endfunc
188 func Test_retab_error()
189 call assert_fails('retab -1', 'E487:')
190 call assert_fails('retab! -1', 'E487:')
191+ call assert_fails('ret -1000', 'E487:')
192+ call assert_fails('ret 10000', 'E475:')
193+ call assert_fails('ret 80000000000000000000', 'E475:')
194 endfunc
195Index: git/src/version.c
196===================================================================
197--- git.orig/src/version.c
198+++ git/src/version.c
199@@ -743,6 +743,8 @@ static char *(features[]) =
200 static int included_patches[] =
201 { /* Add new patch number below this line */
202 /**/
203+ 3402,
204+/**/
205 0
206 };
207
diff --git a/meta/recipes-support/vim/files/disable_acl_header_check.patch b/meta/recipes-support/vim/files/disable_acl_header_check.patch
index 33089162b4..533138245d 100644
--- a/meta/recipes-support/vim/files/disable_acl_header_check.patch
+++ b/meta/recipes-support/vim/files/disable_acl_header_check.patch
@@ -13,11 +13,11 @@ Signed-off-by: Changqing Li <changqing.li@windriver.com>
13 src/configure.ac | 3 ++- 13 src/configure.ac | 3 ++-
14 1 file changed, 2 insertions(+), 1 deletion(-) 14 1 file changed, 2 insertions(+), 1 deletion(-)
15 15
16diff --git a/src/configure.ac b/src/configure.ac 16Index: git/src/configure.ac
17index 2d409b3ca06a..dbcaf6140263 100644 17===================================================================
18--- a/src/configure.ac 18--- git.orig/src/configure.ac
19+++ b/src/configure.ac 19+++ git/src/configure.ac
20@@ -3257,7 +3257,7 @@ AC_CHECK_HEADERS(stdint.h stdlib.h string.h \ 20@@ -3292,7 +3292,7 @@ AC_CHECK_HEADERS(stdint.h stdlib.h strin
21 sys/systeminfo.h locale.h sys/stream.h termios.h \ 21 sys/systeminfo.h locale.h sys/stream.h termios.h \
22 libc.h sys/statfs.h poll.h sys/poll.h pwd.h \ 22 libc.h sys/statfs.h poll.h sys/poll.h pwd.h \
23 utime.h sys/param.h sys/ptms.h libintl.h libgen.h \ 23 utime.h sys/param.h sys/ptms.h libintl.h libgen.h \
@@ -26,7 +26,7 @@ index 2d409b3ca06a..dbcaf6140263 100644
26 sys/access.h sys/sysinfo.h wchar.h wctype.h) 26 sys/access.h sys/sysinfo.h wchar.h wctype.h)
27 27
28 dnl sys/ptem.h depends on sys/stream.h on Solaris 28 dnl sys/ptem.h depends on sys/stream.h on Solaris
29@@ -3886,6 +3886,7 @@ AC_ARG_ENABLE(acl, 29@@ -3974,6 +3974,7 @@ AC_ARG_ENABLE(acl,
30 , [enable_acl="yes"]) 30 , [enable_acl="yes"])
31 if test "$enable_acl" = "yes"; then 31 if test "$enable_acl" = "yes"; then
32 AC_MSG_RESULT(no) 32 AC_MSG_RESULT(no)
@@ -34,6 +34,3 @@ index 2d409b3ca06a..dbcaf6140263 100644
34 AC_CHECK_LIB(posix1e, acl_get_file, [LIBS="$LIBS -lposix1e"], 34 AC_CHECK_LIB(posix1e, acl_get_file, [LIBS="$LIBS -lposix1e"],
35 AC_CHECK_LIB(acl, acl_get_file, [LIBS="$LIBS -lacl" 35 AC_CHECK_LIB(acl, acl_get_file, [LIBS="$LIBS -lacl"
36 AC_CHECK_LIB(attr, fgetxattr, LIBS="$LIBS -lattr",,)],,),) 36 AC_CHECK_LIB(attr, fgetxattr, LIBS="$LIBS -lattr",,)],,),)
37--
382.7.4
39
diff --git a/meta/recipes-support/vim/files/no-path-adjust.patch b/meta/recipes-support/vim/files/no-path-adjust.patch
index 05c2d803f6..9d6da80913 100644
--- a/meta/recipes-support/vim/files/no-path-adjust.patch
+++ b/meta/recipes-support/vim/files/no-path-adjust.patch
@@ -7,9 +7,11 @@ Upstream-Status: Pending
7 7
8Signed-off-by: Joe Slater <joe.slater@windriver.com> 8Signed-off-by: Joe Slater <joe.slater@windriver.com>
9 9
10--- a/src/Makefile 10Index: git/src/Makefile
11+++ b/src/Makefile 11===================================================================
12@@ -2507,11 +2507,14 @@ installtools: $(TOOLS) $(DESTDIR)$(exec_ 12--- git.orig/src/Makefile
13+++ git/src/Makefile
14@@ -2565,11 +2565,14 @@ installtools: $(TOOLS) $(DESTDIR)$(exec_
13 rm -rf $$cvs; \ 15 rm -rf $$cvs; \
14 fi 16 fi
15 -chmod $(FILEMOD) $(DEST_TOOLS)/* 17 -chmod $(FILEMOD) $(DEST_TOOLS)/*
diff --git a/meta/recipes-support/vim/files/racefix.patch b/meta/recipes-support/vim/files/racefix.patch
index 48dca44cad..1cb8fb442f 100644
--- a/meta/recipes-support/vim/files/racefix.patch
+++ b/meta/recipes-support/vim/files/racefix.patch
@@ -9,9 +9,9 @@ Index: git/src/po/Makefile
9=================================================================== 9===================================================================
10--- git.orig/src/po/Makefile 10--- git.orig/src/po/Makefile
11+++ git/src/po/Makefile 11+++ git/src/po/Makefile
12@@ -165,17 +165,16 @@ $(PACKAGE).pot: ../*.c ../if_perl.xs ../ 12@@ -207,17 +207,16 @@ $(PACKAGE).pot: $(PO_INPUTLIST) $(PO_VIM
13 po/gvim.desktop.in po/vim.desktop.in 13 # Delete the temporary files
14 mv -f ../$(PACKAGE).po $(PACKAGE).pot 14 rm *.js
15 15
16-vim.desktop: vim.desktop.in $(POFILES) 16-vim.desktop: vim.desktop.in $(POFILES)
17+LINGUAS: 17+LINGUAS:
diff --git a/meta/recipes-support/vim/files/vim-add-knob-whether-elf.h-are-checked.patch b/meta/recipes-support/vim/files/vim-add-knob-whether-elf.h-are-checked.patch
index 37914d4cd9..5284ba45b6 100644
--- a/meta/recipes-support/vim/files/vim-add-knob-whether-elf.h-are-checked.patch
+++ b/meta/recipes-support/vim/files/vim-add-knob-whether-elf.h-are-checked.patch
@@ -14,11 +14,11 @@ Signed-off-by: Changqing Li <changqing.li@windriver.com>
14 src/configure.ac | 7 +++++++ 14 src/configure.ac | 7 +++++++
15 1 file changed, 7 insertions(+) 15 1 file changed, 7 insertions(+)
16 16
17diff --git a/src/configure.ac b/src/configure.ac 17Index: git/src/configure.ac
18index 0ee86ad..64736f0 100644 18===================================================================
19--- a/src/configure.ac 19--- git.orig/src/configure.ac
20+++ b/src/configure.ac 20+++ git/src/configure.ac
21@@ -3192,11 +3192,18 @@ AC_TRY_COMPILE([#include <stdio.h>], [int x __attribute__((unused));], 21@@ -3264,11 +3264,18 @@ AC_TRY_COMPILE([#include <stdio.h>], [in
22 AC_MSG_RESULT(no)) 22 AC_MSG_RESULT(no))
23 23
24 dnl Checks for header files. 24 dnl Checks for header files.
@@ -37,6 +37,3 @@ index 0ee86ad..64736f0 100644
37 37
38 AC_HEADER_DIRENT 38 AC_HEADER_DIRENT
39 39
40--
412.7.4
42
diff --git a/meta/recipes-support/vim/vim.inc b/meta/recipes-support/vim/vim.inc
index 864006192b..c124596e8d 100644
--- a/meta/recipes-support/vim/vim.inc
+++ b/meta/recipes-support/vim/vim.inc
@@ -8,8 +8,10 @@ BUGTRACKER = "https://github.com/vim/vim/issues"
8DEPENDS = "ncurses gettext-native" 8DEPENDS = "ncurses gettext-native"
9# vimdiff doesn't like busybox diff 9# vimdiff doesn't like busybox diff
10RSUGGESTS_${PN} = "diffutils" 10RSUGGESTS_${PN} = "diffutils"
11
11LICENSE = "vim" 12LICENSE = "vim"
12LIC_FILES_CHKSUM = "file://runtime/doc/uganda.txt;endline=287;md5=a19edd7ec70d573a005d9e509375a99a" 13LIC_FILES_CHKSUM = "file://LICENSE;md5=6b30ea4fa660c483b619924bc709ef99 \
14 file://runtime/doc/uganda.txt;md5=a3f193c20c6faff93c69185d5d070535"
13 15
14SRC_URI = "git://github.com/vim/vim.git;branch=master;protocol=https \ 16SRC_URI = "git://github.com/vim/vim.git;branch=master;protocol=https \
15 file://disable_acl_header_check.patch \ 17 file://disable_acl_header_check.patch \
@@ -17,17 +19,10 @@ SRC_URI = "git://github.com/vim/vim.git;branch=master;protocol=https \
17 file://0001-src-Makefile-improve-reproducibility.patch \ 19 file://0001-src-Makefile-improve-reproducibility.patch \
18 file://no-path-adjust.patch \ 20 file://no-path-adjust.patch \
19 file://racefix.patch \ 21 file://racefix.patch \
20 file://CVE-2021-3778.patch \
21 file://CVE-2021-3796.patch \
22 file://b7081e135a16091c93f6f5f7525a5c58fb7ca9f9.patch \
23 file://CVE-2021-3903.patch \
24 file://CVE-2021-3872.patch \
25 file://CVE-2021-3875.patch \
26 file://CVE-2021-3927.patch \
27 file://CVE-2021-3928.patch \
28" 22"
29 23
30SRCREV = "98056533b96b6b5d8849641de93185dd7bcadc44" 24PV .= ".4524"
25SRCREV = "d8f8629b1bf566e1dada7515e9b146c69e5d9757"
31 26
32# Do not consider .z in x.y.z, as that is updated with every commit 27# Do not consider .z in x.y.z, as that is updated with every commit
33UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+)\.0" 28UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+)\.0"
diff --git a/scripts/buildhistory-diff b/scripts/buildhistory-diff
index 3bd40a2a1e..a6e785aa23 100755
--- a/scripts/buildhistory-diff
+++ b/scripts/buildhistory-diff
@@ -11,7 +11,6 @@
11import sys 11import sys
12import os 12import os
13import argparse 13import argparse
14from distutils.version import LooseVersion
15 14
16# Ensure PythonGit is installed (buildhistory_analysis needs it) 15# Ensure PythonGit is installed (buildhistory_analysis needs it)
17try: 16try:
@@ -73,10 +72,6 @@ def main():
73 parser = get_args_parser() 72 parser = get_args_parser()
74 args = parser.parse_args() 73 args = parser.parse_args()
75 74
76 if LooseVersion(git.__version__) < '0.3.1':
77 sys.stderr.write("Version of GitPython is too old, please install GitPython (python-git) 0.3.1 or later in order to use this script\n")
78 sys.exit(1)
79
80 if len(args.revisions) > 2: 75 if len(args.revisions) > 2:
81 sys.stderr.write('Invalid argument(s) specified: %s\n\n' % ' '.join(args.revisions[2:])) 76 sys.stderr.write('Invalid argument(s) specified: %s\n\n' % ' '.join(args.revisions[2:]))
82 parser.print_help() 77 parser.print_help()
diff --git a/scripts/lib/checklayer/cases/common.py b/scripts/lib/checklayer/cases/common.py
index b82304e361..4495f71b24 100644
--- a/scripts/lib/checklayer/cases/common.py
+++ b/scripts/lib/checklayer/cases/common.py
@@ -14,7 +14,7 @@ class CommonCheckLayer(OECheckLayerTestCase):
14 # The top-level README file may have a suffix (like README.rst or README.txt). 14 # The top-level README file may have a suffix (like README.rst or README.txt).
15 readme_files = glob.glob(os.path.join(self.tc.layer['path'], '[Rr][Ee][Aa][Dd][Mm][Ee]*')) 15 readme_files = glob.glob(os.path.join(self.tc.layer['path'], '[Rr][Ee][Aa][Dd][Mm][Ee]*'))
16 self.assertTrue(len(readme_files) > 0, 16 self.assertTrue(len(readme_files) > 0,
17 msg="Layer doesn't contains README file.") 17 msg="Layer doesn't contain a README file.")
18 18
19 # There might be more than one file matching the file pattern above 19 # There might be more than one file matching the file pattern above
20 # (for example, README.rst and README-COPYING.rst). The one with the shortest 20 # (for example, README.rst and README-COPYING.rst). The one with the shortest
diff --git a/scripts/lib/devtool/deploy.py b/scripts/lib/devtool/deploy.py
index 833322571f..e14a587417 100644
--- a/scripts/lib/devtool/deploy.py
+++ b/scripts/lib/devtool/deploy.py
@@ -170,7 +170,7 @@ def deploy(args, config, basepath, workspace):
170 srcdir = recipe_outdir 170 srcdir = recipe_outdir
171 recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'devtool-deploy-target-stripped') 171 recipe_outdir = os.path.join(rd.getVar('WORKDIR'), 'devtool-deploy-target-stripped')
172 if os.path.isdir(recipe_outdir): 172 if os.path.isdir(recipe_outdir):
173 bb.utils.remove(recipe_outdir, True) 173 exec_fakeroot(rd, "rm -rf %s" % recipe_outdir, shell=True)
174 exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True) 174 exec_fakeroot(rd, "cp -af %s %s" % (os.path.join(srcdir, '.'), recipe_outdir), shell=True)
175 os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or '']) 175 os.environ['PATH'] = ':'.join([os.environ['PATH'], rd.getVar('PATH') or ''])
176 oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'), 176 oe.package.strip_execs(args.recipename, recipe_outdir, rd.getVar('STRIP'), rd.getVar('libdir'),
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 116bdfd697..b9f9c80367 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -366,7 +366,7 @@ def supports_srcrev(uri):
366def reformat_git_uri(uri): 366def reformat_git_uri(uri):
367 '''Convert any http[s]://....git URI into git://...;protocol=http[s]''' 367 '''Convert any http[s]://....git URI into git://...;protocol=http[s]'''
368 checkuri = uri.split(';', 1)[0] 368 checkuri = uri.split(';', 1)[0]
369 if checkuri.endswith('.git') or '/git/' in checkuri or re.match('https?://github.com/[^/]+/[^/]+/?$', checkuri): 369 if checkuri.endswith('.git') or '/git/' in checkuri or re.match('https?://git(hub|lab).com/[^/]+/[^/]+/?$', checkuri):
370 # Appends scheme if the scheme is missing 370 # Appends scheme if the scheme is missing
371 if not '://' in uri: 371 if not '://' in uri:
372 uri = 'git://' + uri 372 uri = 'git://' + uri
@@ -389,9 +389,6 @@ def reformat_git_uri(uri):
389 parms.update({('protocol', 'ssh')}) 389 parms.update({('protocol', 'ssh')})
390 elif (scheme == "http" or scheme == 'https' or scheme == 'ssh') and not ('protocol' in parms): 390 elif (scheme == "http" or scheme == 'https' or scheme == 'ssh') and not ('protocol' in parms):
391 parms.update({('protocol', scheme)}) 391 parms.update({('protocol', scheme)})
392 # We assume 'master' branch if not set
393 if not 'branch' in parms:
394 parms.update({('branch', 'master')})
395 # Always append 'git://' 392 # Always append 'git://'
396 fUrl = bb.fetch2.encodeurl(('git', host, path, user, pswd, parms)) 393 fUrl = bb.fetch2.encodeurl(('git', host, path, user, pswd, parms))
397 return fUrl 394 return fUrl
@@ -438,7 +435,7 @@ def create_recipe(args):
438 if args.binary: 435 if args.binary:
439 # Assume the archive contains the directory structure verbatim 436 # Assume the archive contains the directory structure verbatim
440 # so we need to extract to a subdirectory 437 # so we need to extract to a subdirectory
441 fetchuri += ';subdir=${BP}' 438 fetchuri += ';subdir=${BPN}'
442 srcuri = fetchuri 439 srcuri = fetchuri
443 rev_re = re.compile(';rev=([^;]+)') 440 rev_re = re.compile(';rev=([^;]+)')
444 res = rev_re.search(srcuri) 441 res = rev_re.search(srcuri)
@@ -481,6 +478,9 @@ def create_recipe(args):
481 storeTagName = params['tag'] 478 storeTagName = params['tag']
482 params['nobranch'] = '1' 479 params['nobranch'] = '1'
483 del params['tag'] 480 del params['tag']
481 # Assume 'master' branch if not set
482 if scheme in ['git', 'gitsm'] and 'branch' not in params and 'nobranch' not in params:
483 params['branch'] = 'master'
484 fetchuri = bb.fetch2.encodeurl((scheme, network, path, user, passwd, params)) 484 fetchuri = bb.fetch2.encodeurl((scheme, network, path, user, passwd, params))
485 485
486 tmpparent = tinfoil.config_data.getVar('BASE_WORKDIR') 486 tmpparent = tinfoil.config_data.getVar('BASE_WORKDIR')
@@ -530,10 +530,9 @@ def create_recipe(args):
530 # Remove HEAD reference point and drop remote prefix 530 # Remove HEAD reference point and drop remote prefix
531 get_branch = [x.split('/', 1)[1] for x in get_branch if not x.startswith('origin/HEAD')] 531 get_branch = [x.split('/', 1)[1] for x in get_branch if not x.startswith('origin/HEAD')]
532 if 'master' in get_branch: 532 if 'master' in get_branch:
533 # If it is master, we do not need to append 'branch=master' as this is default.
534 # Even with the case where get_branch has multiple objects, if 'master' is one 533 # Even with the case where get_branch has multiple objects, if 'master' is one
535 # of them, we should default take from 'master' 534 # of them, we should default take from 'master'
536 srcbranch = '' 535 srcbranch = 'master'
537 elif len(get_branch) == 1: 536 elif len(get_branch) == 1:
538 # If 'master' isn't in get_branch and get_branch contains only ONE object, then store result into 'srcbranch' 537 # If 'master' isn't in get_branch and get_branch contains only ONE object, then store result into 'srcbranch'
539 srcbranch = get_branch[0] 538 srcbranch = get_branch[0]
@@ -546,8 +545,8 @@ def create_recipe(args):
546 # Since we might have a value in srcbranch, we need to 545 # Since we might have a value in srcbranch, we need to
547 # recontruct the srcuri to include 'branch' in params. 546 # recontruct the srcuri to include 'branch' in params.
548 scheme, network, path, user, passwd, params = bb.fetch2.decodeurl(srcuri) 547 scheme, network, path, user, passwd, params = bb.fetch2.decodeurl(srcuri)
549 if srcbranch: 548 if scheme in ['git', 'gitsm']:
550 params['branch'] = srcbranch 549 params['branch'] = srcbranch or 'master'
551 550
552 if storeTagName and scheme in ['git', 'gitsm']: 551 if storeTagName and scheme in ['git', 'gitsm']:
553 # Check srcrev using tag and check validity of the tag 552 # Check srcrev using tag and check validity of the tag
@@ -606,7 +605,7 @@ def create_recipe(args):
606 splitline = line.split() 605 splitline = line.split()
607 if len(splitline) > 1: 606 if len(splitline) > 1:
608 if splitline[0] == 'origin' and scriptutils.is_src_url(splitline[1]): 607 if splitline[0] == 'origin' and scriptutils.is_src_url(splitline[1]):
609 srcuri = reformat_git_uri(splitline[1]) 608 srcuri = reformat_git_uri(splitline[1]) + ';branch=master'
610 srcsubdir = 'git' 609 srcsubdir = 'git'
611 break 610 break
612 611
diff --git a/scripts/lib/recipetool/create_buildsys.py b/scripts/lib/recipetool/create_buildsys.py
index 35a97c9345..5015634476 100644
--- a/scripts/lib/recipetool/create_buildsys.py
+++ b/scripts/lib/recipetool/create_buildsys.py
@@ -545,7 +545,7 @@ class AutotoolsRecipeHandler(RecipeHandler):
545 deps.append('zlib') 545 deps.append('zlib')
546 elif keyword in ('AX_CHECK_OPENSSL', 'AX_LIB_CRYPTO'): 546 elif keyword in ('AX_CHECK_OPENSSL', 'AX_LIB_CRYPTO'):
547 deps.append('openssl') 547 deps.append('openssl')
548 elif keyword == 'AX_LIB_CURL': 548 elif keyword in ('AX_LIB_CURL', 'LIBCURL_CHECK_CONFIG'):
549 deps.append('curl') 549 deps.append('curl')
550 elif keyword == 'AX_LIB_BEECRYPT': 550 elif keyword == 'AX_LIB_BEECRYPT':
551 deps.append('beecrypt') 551 deps.append('beecrypt')
@@ -624,6 +624,7 @@ class AutotoolsRecipeHandler(RecipeHandler):
624 'AX_CHECK_OPENSSL', 624 'AX_CHECK_OPENSSL',
625 'AX_LIB_CRYPTO', 625 'AX_LIB_CRYPTO',
626 'AX_LIB_CURL', 626 'AX_LIB_CURL',
627 'LIBCURL_CHECK_CONFIG',
627 'AX_LIB_BEECRYPT', 628 'AX_LIB_BEECRYPT',
628 'AX_LIB_EXPAT', 629 'AX_LIB_EXPAT',
629 'AX_LIB_GCRYPT', 630 'AX_LIB_GCRYPT',
diff --git a/scripts/lib/scriptutils.py b/scripts/lib/scriptutils.py
index 3164171eb2..47a08194d0 100644
--- a/scripts/lib/scriptutils.py
+++ b/scripts/lib/scriptutils.py
@@ -18,7 +18,8 @@ import sys
18import tempfile 18import tempfile
19import threading 19import threading
20import importlib 20import importlib
21from importlib import machinery 21import importlib.machinery
22import importlib.util
22 23
23class KeepAliveStreamHandler(logging.StreamHandler): 24class KeepAliveStreamHandler(logging.StreamHandler):
24 def __init__(self, keepalive=True, **kwargs): 25 def __init__(self, keepalive=True, **kwargs):
@@ -82,7 +83,9 @@ def load_plugins(logger, plugins, pluginpath):
82 logger.debug('Loading plugin %s' % name) 83 logger.debug('Loading plugin %s' % name)
83 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] ) 84 spec = importlib.machinery.PathFinder.find_spec(name, path=[pluginpath] )
84 if spec: 85 if spec:
85 return spec.loader.load_module() 86 mod = importlib.util.module_from_spec(spec)
87 spec.loader.exec_module(mod)
88 return mod
86 89
87 def plugin_name(filename): 90 def plugin_name(filename):
88 return os.path.splitext(os.path.basename(filename))[0] 91 return os.path.splitext(os.path.basename(filename))[0]
diff --git a/scripts/lib/wic/engine.py b/scripts/lib/wic/engine.py
index 018815b966..674ccfc244 100644
--- a/scripts/lib/wic/engine.py
+++ b/scripts/lib/wic/engine.py
@@ -19,10 +19,10 @@ import os
19import tempfile 19import tempfile
20import json 20import json
21import subprocess 21import subprocess
22import shutil
22import re 23import re
23 24
24from collections import namedtuple, OrderedDict 25from collections import namedtuple, OrderedDict
25from distutils.spawn import find_executable
26 26
27from wic import WicError 27from wic import WicError
28from wic.filemap import sparse_copy 28from wic.filemap import sparse_copy
@@ -245,7 +245,7 @@ class Disk:
245 for path in pathlist.split(':'): 245 for path in pathlist.split(':'):
246 self.paths = "%s%s:%s" % (native_sysroot, path, self.paths) 246 self.paths = "%s%s:%s" % (native_sysroot, path, self.paths)
247 247
248 self.parted = find_executable("parted", self.paths) 248 self.parted = shutil.which("parted", path=self.paths)
249 if not self.parted: 249 if not self.parted:
250 raise WicError("Can't find executable parted") 250 raise WicError("Can't find executable parted")
251 251
@@ -283,7 +283,7 @@ class Disk:
283 "resize2fs", "mkswap", "mkdosfs", "debugfs","blkid"): 283 "resize2fs", "mkswap", "mkdosfs", "debugfs","blkid"):
284 aname = "_%s" % name 284 aname = "_%s" % name
285 if aname not in self.__dict__: 285 if aname not in self.__dict__:
286 setattr(self, aname, find_executable(name, self.paths)) 286 setattr(self, aname, shutil.which(name, path=self.paths))
287 if aname not in self.__dict__ or self.__dict__[aname] is None: 287 if aname not in self.__dict__ or self.__dict__[aname] is None:
288 raise WicError("Can't find executable '{}'".format(name)) 288 raise WicError("Can't find executable '{}'".format(name))
289 return self.__dict__[aname] 289 return self.__dict__[aname]
diff --git a/scripts/lib/wic/misc.py b/scripts/lib/wic/misc.py
index 57c042c503..3e11822996 100644
--- a/scripts/lib/wic/misc.py
+++ b/scripts/lib/wic/misc.py
@@ -16,9 +16,9 @@ import logging
16import os 16import os
17import re 17import re
18import subprocess 18import subprocess
19import shutil
19 20
20from collections import defaultdict 21from collections import defaultdict
21from distutils import spawn
22 22
23from wic import WicError 23from wic import WicError
24 24
@@ -122,7 +122,7 @@ def find_executable(cmd, paths):
122 if provided and "%s-native" % recipe in provided: 122 if provided and "%s-native" % recipe in provided:
123 return True 123 return True
124 124
125 return spawn.find_executable(cmd, paths) 125 return shutil.which(cmd, path=paths)
126 126
127def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""): 127def exec_native_cmd(cmd_and_args, native_sysroot, pseudo=""):
128 """ 128 """
diff --git a/scripts/lib/wic/pluginbase.py b/scripts/lib/wic/pluginbase.py
index d9b4e57747..b64568339b 100644
--- a/scripts/lib/wic/pluginbase.py
+++ b/scripts/lib/wic/pluginbase.py
@@ -9,9 +9,11 @@ __all__ = ['ImagerPlugin', 'SourcePlugin']
9 9
10import os 10import os
11import logging 11import logging
12import types
12 13
13from collections import defaultdict 14from collections import defaultdict
14from importlib.machinery import SourceFileLoader 15import importlib
16import importlib.util
15 17
16from wic import WicError 18from wic import WicError
17from wic.misc import get_bitbake_var 19from wic.misc import get_bitbake_var
@@ -54,7 +56,9 @@ class PluginMgr:
54 mname = fname[:-3] 56 mname = fname[:-3]
55 mpath = os.path.join(ppath, fname) 57 mpath = os.path.join(ppath, fname)
56 logger.debug("loading plugin module %s", mpath) 58 logger.debug("loading plugin module %s", mpath)
57 SourceFileLoader(mname, mpath).load_module() 59 spec = importlib.util.spec_from_file_location(mname, mpath)
60 module = importlib.util.module_from_spec(spec)
61 spec.loader.exec_module(module)
58 62
59 return PLUGINS.get(ptype) 63 return PLUGINS.get(ptype)
60 64
diff --git a/scripts/lib/wic/plugins/imager/direct.py b/scripts/lib/wic/plugins/imager/direct.py
index ea709e8c54..2c5d5efe0e 100644
--- a/scripts/lib/wic/plugins/imager/direct.py
+++ b/scripts/lib/wic/plugins/imager/direct.py
@@ -258,6 +258,8 @@ class DirectPlugin(ImagerPlugin):
258 if part.mountpoint == "/": 258 if part.mountpoint == "/":
259 if part.uuid: 259 if part.uuid:
260 return "PARTUUID=%s" % part.uuid 260 return "PARTUUID=%s" % part.uuid
261 elif part.label:
262 return "PARTLABEL=%s" % part.label
261 else: 263 else:
262 suffix = 'p' if part.disk.startswith('mmcblk') else '' 264 suffix = 'p' if part.disk.startswith('mmcblk') else ''
263 return "/dev/%s%s%-d" % (part.disk, suffix, part.realnum) 265 return "/dev/%s%s%-d" % (part.disk, suffix, part.realnum)
diff --git a/scripts/runqemu b/scripts/runqemu
index f3527a4412..f9a1a0da32 100755
--- a/scripts/runqemu
+++ b/scripts/runqemu
@@ -1573,7 +1573,8 @@ def main():
1573 1573
1574 def sigterm_handler(signum, frame): 1574 def sigterm_handler(signum, frame):
1575 logger.info("SIGTERM received") 1575 logger.info("SIGTERM received")
1576 os.kill(config.qemupid, signal.SIGTERM) 1576 if config.qemupid:
1577 os.kill(config.qemupid, signal.SIGTERM)
1577 config.cleanup() 1578 config.cleanup()
1578 # Deliberately ignore the return code of 'tput smam'. 1579 # Deliberately ignore the return code of 'tput smam'.
1579 subprocess.call(["tput", "smam"]) 1580 subprocess.call(["tput", "smam"])
diff --git a/scripts/runqemu-ifdown b/scripts/runqemu-ifdown
index a104c37bf8..e0eb5344c6 100755
--- a/scripts/runqemu-ifdown
+++ b/scripts/runqemu-ifdown
@@ -64,3 +64,4 @@ n=$[ (`echo $TAP | sed 's/tap//'` * 2) + 1 ]
64dest=$[ (`echo $TAP | sed 's/tap//'` * 2) + 2 ] 64dest=$[ (`echo $TAP | sed 's/tap//'` * 2) + 2 ]
65$IPTABLES -D POSTROUTING -t nat -j MASQUERADE -s 192.168.7.$n/32 65$IPTABLES -D POSTROUTING -t nat -j MASQUERADE -s 192.168.7.$n/32
66$IPTABLES -D POSTROUTING -t nat -j MASQUERADE -s 192.168.7.$dest/32 66$IPTABLES -D POSTROUTING -t nat -j MASQUERADE -s 192.168.7.$dest/32
67true
diff --git a/scripts/wic b/scripts/wic
index a741aed364..c0bc0e6fe8 100755
--- a/scripts/wic
+++ b/scripts/wic
@@ -22,9 +22,9 @@ import sys
22import argparse 22import argparse
23import logging 23import logging
24import subprocess 24import subprocess
25import shutil
25 26
26from collections import namedtuple 27from collections import namedtuple
27from distutils import spawn
28 28
29# External modules 29# External modules
30scripts_path = os.path.dirname(os.path.realpath(__file__)) 30scripts_path = os.path.dirname(os.path.realpath(__file__))
@@ -47,7 +47,7 @@ if os.environ.get('SDKTARGETSYSROOT'):
47 break 47 break
48 sdkroot = os.path.dirname(sdkroot) 48 sdkroot = os.path.dirname(sdkroot)
49 49
50bitbake_exe = spawn.find_executable('bitbake') 50bitbake_exe = shutil.which('bitbake')
51if bitbake_exe: 51if bitbake_exe:
52 bitbake_path = scriptpath.add_bitbake_lib_path() 52 bitbake_path = scriptpath.add_bitbake_lib_path()
53 import bb 53 import bb
@@ -159,6 +159,9 @@ def wic_create_subcommand(options, usage_str):
159 "(Use -e/--image-name to specify it)") 159 "(Use -e/--image-name to specify it)")
160 native_sysroot = options.native_sysroot 160 native_sysroot = options.native_sysroot
161 161
162 if options.kernel_dir:
163 kernel_dir = options.kernel_dir
164
162 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)): 165 if not options.vars_dir and (not native_sysroot or not os.path.isdir(native_sysroot)):
163 logger.info("Building wic-tools...\n") 166 logger.info("Building wic-tools...\n")
164 subprocess.check_call(["bitbake", "wic-tools"]) 167 subprocess.check_call(["bitbake", "wic-tools"])
diff --git a/scripts/yocto-check-layer b/scripts/yocto-check-layer
index 6975b09502..00a16d18fc 100755
--- a/scripts/yocto-check-layer
+++ b/scripts/yocto-check-layer
@@ -41,6 +41,12 @@ def test_layer(td, layer, test_software_layer_signatures):
41 tc.loadTests(CASES_PATHS) 41 tc.loadTests(CASES_PATHS)
42 return tc.runTests() 42 return tc.runTests()
43 43
44def dump_layer_debug(layer):
45 logger.debug("Found layer %s (%s)" % (layer["name"], layer["path"]))
46 collections = layer.get("collections", {})
47 if collections:
48 logger.debug("%s collections: %s" % (layer["name"], ", ".join(collections)))
49
44def main(): 50def main():
45 parser = argparse.ArgumentParser( 51 parser = argparse.ArgumentParser(
46 description="Yocto Project layer checking tool", 52 description="Yocto Project layer checking tool",
@@ -106,6 +112,13 @@ def main():
106 else: 112 else:
107 dep_layers = layers 113 dep_layers = layers
108 114
115 logger.debug("Found additional layers:")
116 for l in additional_layers:
117 dump_layer_debug(l)
118 logger.debug("Found dependency layers:")
119 for l in dep_layers:
120 dump_layer_debug(l)
121
109 logger.info("Detected layers:") 122 logger.info("Detected layers:")
110 for layer in layers: 123 for layer in layers:
111 if layer['type'] == LayerType.ERROR_BSP_DISTRO: 124 if layer['type'] == LayerType.ERROR_BSP_DISTRO: