From ff6a9ad5c724067cbeccb3157b22c808f6569d20 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Thu, 29 May 2025 15:54:45 +0200 Subject: [PATCH 001/150] Add a few example setups of fuzzing campaigns --- tools/captain/tests/aflplusplus.auto | 24 ++++++++++++++++++++++++ tools/captain/tests/aflplusplus.debug | 24 ++++++++++++++++++++++++ tools/captain/tests/report_2025.auto | 27 +++++++++++++++++++++++++++ tools/captain/tests/report_2025.debug | 27 +++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 tools/captain/tests/aflplusplus.auto create mode 100644 tools/captain/tests/aflplusplus.debug create mode 100644 tools/captain/tests/report_2025.auto create mode 100644 tools/captain/tests/report_2025.debug diff --git a/tools/captain/tests/aflplusplus.auto b/tools/captain/tests/aflplusplus.auto new file mode 100644 index 000000000..eed59adf6 --- /dev/null +++ b/tools/captain/tests/aflplusplus.auto @@ -0,0 +1,24 @@ +### +## Configuration parameters +### + +source captainrc + +WORKDIR=workdir_aflplusplus +REPEAT=1 +TIMEOUT=10m + + +### +## Campaigns to run +### + +FUZZERS=( + aflplusplus +) + +aflplusplus_TARGETS=(libpng) + +### +## This script should finish in 1*10=10 minutes (one core). +### diff --git a/tools/captain/tests/aflplusplus.debug b/tools/captain/tests/aflplusplus.debug new file mode 100644 index 000000000..dd81dbd5a --- /dev/null +++ b/tools/captain/tests/aflplusplus.debug @@ -0,0 +1,24 @@ +### +## Configuration parameters +### + +source captainrc + +WORKDIR=workdir_aflplusplus +REPEAT=1 +TIMEOUT=10m +MAGMA_DEBUG=1 + +### +## Campaigns to run +### + +FUZZERS=( + aflplusplus +) + +aflplusplus_TARGETS=(libpng) + +### +## This script should finish in 1*10=10 minutes (one core). +### diff --git a/tools/captain/tests/report_2025.auto b/tools/captain/tests/report_2025.auto new file mode 100644 index 000000000..96196d585 --- /dev/null +++ b/tools/captain/tests/report_2025.auto @@ -0,0 +1,27 @@ +### +## Configuration parameters +### + +source captainrc + +WORKDIR=workdir_report_2025 +REPEAT=10 +TIMEOUT=24h +ISAN=1 + + +### +## Campaigns to run +### + +FUZZERS=( + aflplusplus + honggfuzz + libfuzzer +) + +# By default, all targets (21 programs) will be fuzzed + +### +## This script should finish in 21*24 hours (one core). +### diff --git a/tools/captain/tests/report_2025.debug b/tools/captain/tests/report_2025.debug new file mode 100644 index 000000000..eca3543c0 --- /dev/null +++ b/tools/captain/tests/report_2025.debug @@ -0,0 +1,27 @@ +### +## Configuration parameters +### + +source captainrc + +WORKDIR=workdir_report_2025 +REPEAT=10 +TIMEOUT=24h +ISAN=1 +MAGMA_DEBUG=1 + +### +## Campaigns to run +### + +FUZZERS=( + aflplusplus + honggfuzz + libfuzzer +) + +# By default, all targets (21 programs) will be fuzzed + +### +## This script should finish in 21*24 hours (one core). +### From 0b0f4551d0613125c091367ef3f6e62d6f2ff551 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Thu, 29 May 2025 16:42:09 +0200 Subject: [PATCH 002/150] Fix duration --- tools/captain/tests/report_2025.auto | 2 +- tools/captain/tests/report_2025.debug | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/captain/tests/report_2025.auto b/tools/captain/tests/report_2025.auto index 96196d585..1e616d7d1 100644 --- a/tools/captain/tests/report_2025.auto +++ b/tools/captain/tests/report_2025.auto @@ -23,5 +23,5 @@ FUZZERS=( # By default, all targets (21 programs) will be fuzzed ### -## This script should finish in 21*24 hours (one core). +## This script should finish in 3*21*24 hours (one core). ### diff --git a/tools/captain/tests/report_2025.debug b/tools/captain/tests/report_2025.debug index eca3543c0..de7191e11 100644 --- a/tools/captain/tests/report_2025.debug +++ b/tools/captain/tests/report_2025.debug @@ -23,5 +23,5 @@ FUZZERS=( # By default, all targets (21 programs) will be fuzzed ### -## This script should finish in 21*24 hours (one core). +## This script should finish in 3*21*24 hours (one core). ### From 41bc4700679d9beb8fa981fbbcbb09f025ea66f6 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 15:37:32 +0100 Subject: [PATCH 003/150] Add gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..6e5adfc46 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +workdir* +__pycache__/ From 91fb55f72ae287c20079d8387b9c399bf67e979c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 15:56:59 +0100 Subject: [PATCH 004/150] Add script to generate target releases list --- gen_target_releases.py | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 gen_target_releases.py diff --git a/gen_target_releases.py b/gen_target_releases.py new file mode 100644 index 000000000..59a9f1fb1 --- /dev/null +++ b/gen_target_releases.py @@ -0,0 +1,87 @@ +#!/usr/bin/python3 + +""" +This script is used to generate a list of releases for a target. The results are written +to a file at path `targets//releases`. The releases file is used to point to +a specific target version while building it using the tools/captain/run.sh script. +""" + +import os +import subprocess +import sys +subprocess.check_call([sys.executable, "-m", "pip", "install", "gitpython"]) + +from git import Repo +from datetime import datetime + +links = { + 'libpng': 'https://github.com/pnggroup/libpng' +} + +repos = [] + +def get_tags(repo_url): + repo_name = repo_url.split('/')[-1].replace('.git', '') + local_path = os.path.join(os.getcwd(), repo_name) + repos.append(local_path) + + if not os.path.exists(local_path): + repo = Repo.clone_from(repo_url, local_path) + print(f'Cloned {repo_url}') + else: + repo = Repo(local_path) + + # get all tags available + year_to_tag = {} + for tag in repo.tags: + tag_date = tag.tag.tagged_date if tag.tag else tag.commit.committed_date + year = datetime.fromtimestamp(tag_date).year + if year not in year_to_tag: + year_to_tag[year] = tag.name + + year_to_tag_sorted = dict(sorted(year_to_tag.items())) + min_year = list(year_to_tag_sorted.keys())[0] + + # fill the gaps + last_tag = 0 + for i in range(min_year, 2025): + if i in year_to_tag_sorted: + last_tag = year_to_tag_sorted[i] + else: + year_to_tag_sorted[i] = last_tag + + year_to_tag_sorted = dict(sorted(year_to_tag_sorted.items())) + return year_to_tag_sorted + +for target, link in links.items(): + path_to_releases = os.path.join('targets', target, 'releases') + + if isinstance(link, str): # git repo + year_to_tag = get_tags(link) + print(f'Got tags of {target}') + releases = [ + f'{target}_PIONEER="{link}"\n', + ] + for i in range(2022, 2025): + releases.append(f'{target}_LEGACY_{i}="{link}"\n') + releases.append(f'{target}_LEGACY_{i}_TAG="{year_to_tag[i]}"\n') + else: # predefined + assert(isinstance(link, dict)) + releases = [ + f'{target}_PIONEER="{link[2024]}"\n', + ] + for i in range(2020, 2025): + if isinstance(link[i], str): + releases.append(f'{target}_LEGACY_{i}="{link[i]}"\n') + else: # git repo, + tag or commit + releases.append(f'{target}_LEGACY_{i}="{link[i][0]}"\n') + releases.append(f'{target}_LEGACY_{i}_TAG="{link[i][1]}"\n') + + with open(path_to_releases, 'w') as f: + for line in releases: + f.write(line) + print(f'Wrote to {path_to_releases}') + +# clean +all_repos = ' '.join(repos) +print(f'rm -rf {all_repos}') From 1ce04c1fad5491d8fcb6c7e77586f3b3e55f950a Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 15:57:17 +0100 Subject: [PATCH 005/150] Add releases for libpng --- targets/libpng/releases | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 targets/libpng/releases diff --git a/targets/libpng/releases b/targets/libpng/releases new file mode 100644 index 000000000..53026fac8 --- /dev/null +++ b/targets/libpng/releases @@ -0,0 +1,7 @@ +libpng_PIONEER="https://github.com/pnggroup/libpng" +libpng_LEGACY_2022="https://github.com/pnggroup/libpng" +libpng_LEGACY_2022_TAG="v1.6.38" +libpng_LEGACY_2023="https://github.com/pnggroup/libpng" +libpng_LEGACY_2023_TAG="v1.6.40" +libpng_LEGACY_2024="https://github.com/pnggroup/libpng" +libpng_LEGACY_2024_TAG="v1.6.41" From 6130a121d64086b1d5bf6300d9a53cd5b18c848f Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:00:30 +0100 Subject: [PATCH 006/150] Provide target version buildarg via captain --- tools/captain/build.sh | 1 + tools/captain/captainrc | 3 +++ 2 files changed, 4 insertions(+) diff --git a/tools/captain/build.sh b/tools/captain/build.sh index 939950029..6553b41a2 100755 --- a/tools/captain/build.sh +++ b/tools/captain/build.sh @@ -45,6 +45,7 @@ set -x docker build -t "$IMG_NAME" \ --build-arg fuzzer_name="$FUZZER" \ --build-arg target_name="$TARGET" \ + --build-arg target_version="$TARGET_VERSION" \ --build-arg USER_ID=$(id -u $USER) \ --build-arg GROUP_ID=$(id -g $USER) \ $mode_flag $isan_flag $harden_flag \ diff --git a/tools/captain/captainrc b/tools/captain/captainrc index 466d21647..3225690c5 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -89,3 +89,6 @@ FUZZERS=(afl aflfast moptafl aflplusplus fairfuzz honggfuzz) # [fuzzer_CAMPAIGN_WORKERS]: overrides the global CAMPAIGN_WORKERS setting # afl_CAMPAIGN_WORKERS=3 + +# [TARGET_VERSION]: target version to be chosen from its releases file +TARGET_VERSION=PIONEER From acb0b0cd42a1be83d9d1a45ab2e8dcf9ac0e6e1d Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:01:18 +0100 Subject: [PATCH 007/150] Add a generic script to fetch target by version --- magma/fetch_target.sh | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 magma/fetch_target.sh diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh new file mode 100644 index 000000000..245d76d03 --- /dev/null +++ b/magma/fetch_target.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +## +# Pre-requirements: +# - env TARGET: path to target work dir +# - env TARGET_NAME: name of the target +# - env TARGET_VERSION: version of target from releases (PIONEER = latest) +## + +source "$TARGET"/releases + +to_fetch_var="$TARGET_NAME"_"$TARGET_VERSION" +to_fetch=${!to_fetch_var} + +if [[ "$to_fetch" =~ ^https://github\.com/.+/.+ ]]; then + git clone "$to_fetch" "$TARGET/repo" +elif [[ "$to_fetch" =~ \.tar\.gz$ ]]; then + wget -O "$TARGET"/repo.tar.gz "$to_fetch" + mkdir "$TARGET"/repo + tar -xf "$TARGET"/repo.tar.gz --strip-components=1 -C "$TARGET"/repo +else + echo "Unsupported link: $to_fetch" + exit +fi \ No newline at end of file From 224afe08e0458dcef89a05ed2651ada416dc3a85 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:03:00 +0100 Subject: [PATCH 008/150] Use new fetch in Dockerfile --- docker/Dockerfile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index e3dd49ab1..0a90410e6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -57,13 +57,19 @@ RUN ${FUZZER}/build.sh ARG target_name ARG target_path=targets/${target_name} -ENV TARGET ${MAGMA_R}/${target_path} +ENV TARGET_NAME ${target_name} +ENV TARGET ${MAGMA_R}/${target_path} +ARG target_version +ENV TARGET_VERSION=${target_version} USER root:root RUN mkdir -p ${TARGET} && chown magma:magma ${TARGET} COPY --chown=magma:magma ${magma_root}/${target_path} ${TARGET}/ RUN ${TARGET}/preinstall.sh USER magma:magma -RUN ${TARGET}/fetch.sh +# TODO: Remove the following line once all targets use fetch_target.sh +# RUN ${TARGET}/fetch.sh +RUN chmod +x ${MAGMA}/fetch_target.sh && \ + ${MAGMA}/fetch_target.sh RUN ${MAGMA}/apply_patches.sh ## Configuration parameters From d87c1c0971dabe01a3f65d3b0d1d20e486394862 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:04:13 +0100 Subject: [PATCH 009/150] Move non applicable patches to failed dir (libpng) --- targets/libpng/patches/{ => failed}/bugs/PNG001.patch | 0 targets/libpng/patches/{ => failed}/bugs/PNG002.patch | 0 targets/libpng/patches/{ => failed}/bugs/PNG003.patch | 0 targets/libpng/patches/{ => failed}/bugs/PNG006.patch | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename targets/libpng/patches/{ => failed}/bugs/PNG001.patch (100%) rename targets/libpng/patches/{ => failed}/bugs/PNG002.patch (100%) rename targets/libpng/patches/{ => failed}/bugs/PNG003.patch (100%) rename targets/libpng/patches/{ => failed}/bugs/PNG006.patch (100%) diff --git a/targets/libpng/patches/bugs/PNG001.patch b/targets/libpng/patches/failed/bugs/PNG001.patch similarity index 100% rename from targets/libpng/patches/bugs/PNG001.patch rename to targets/libpng/patches/failed/bugs/PNG001.patch diff --git a/targets/libpng/patches/bugs/PNG002.patch b/targets/libpng/patches/failed/bugs/PNG002.patch similarity index 100% rename from targets/libpng/patches/bugs/PNG002.patch rename to targets/libpng/patches/failed/bugs/PNG002.patch diff --git a/targets/libpng/patches/bugs/PNG003.patch b/targets/libpng/patches/failed/bugs/PNG003.patch similarity index 100% rename from targets/libpng/patches/bugs/PNG003.patch rename to targets/libpng/patches/failed/bugs/PNG003.patch diff --git a/targets/libpng/patches/bugs/PNG006.patch b/targets/libpng/patches/failed/bugs/PNG006.patch similarity index 100% rename from targets/libpng/patches/bugs/PNG006.patch rename to targets/libpng/patches/failed/bugs/PNG006.patch From 8b1be135650c2bbaf06f2d4ee8ecaf35553ecb8c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:15:49 +0100 Subject: [PATCH 010/150] Remove libpng fetch.sh --- targets/libpng/fetch.sh | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100755 targets/libpng/fetch.sh diff --git a/targets/libpng/fetch.sh b/targets/libpng/fetch.sh deleted file mode 100755 index 09772565c..000000000 --- a/targets/libpng/fetch.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://github.com/glennrp/libpng.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout a37d4836519517bdce6cb9d956092321eca3e73b \ No newline at end of file From 0238670580df167bef89cdbc19251dc39f26937a Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 16:40:58 +0100 Subject: [PATCH 011/150] Update libsndfile to latest version --- gen_target_releases.py | 32 +++++++++++-------- targets/libsndfile/build.sh | 4 +-- targets/libsndfile/fetch.sh | 10 ------ .../{ => failed}/setup/libsndfile.patch | 0 targets/libsndfile/releases | 7 ++++ 5 files changed, 27 insertions(+), 26 deletions(-) delete mode 100755 targets/libsndfile/fetch.sh rename targets/libsndfile/patches/{ => failed}/setup/libsndfile.patch (100%) create mode 100644 targets/libsndfile/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index 59a9f1fb1..7f2e3caab 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -2,32 +2,35 @@ """ This script is used to generate a list of releases for a target. The results are written -to a file at path `targets//releases`. The releases file is used to point to +to a file at path `targets//releases`. The releases file is used to point to a specific target version while building it using the tools/captain/run.sh script. """ import os import subprocess import sys + subprocess.check_call([sys.executable, "-m", "pip", "install", "gitpython"]) from git import Repo from datetime import datetime links = { - 'libpng': 'https://github.com/pnggroup/libpng' + "libpng": "https://github.com/pnggroup/libpng", + "libsndfile": "https://github.com/libsndfile/libsndfile.git", } repos = [] + def get_tags(repo_url): - repo_name = repo_url.split('/')[-1].replace('.git', '') + repo_name = repo_url.split("/")[-1].replace(".git", "") local_path = os.path.join(os.getcwd(), repo_name) repos.append(local_path) if not os.path.exists(local_path): repo = Repo.clone_from(repo_url, local_path) - print(f'Cloned {repo_url}') + print(f"Cloned {repo_url}") else: repo = Repo(local_path) @@ -53,35 +56,36 @@ def get_tags(repo_url): year_to_tag_sorted = dict(sorted(year_to_tag_sorted.items())) return year_to_tag_sorted + for target, link in links.items(): - path_to_releases = os.path.join('targets', target, 'releases') + path_to_releases = os.path.join("targets", target, "releases") - if isinstance(link, str): # git repo + if isinstance(link, str): # git repo year_to_tag = get_tags(link) - print(f'Got tags of {target}') + print(f"Got tags of {target}") releases = [ f'{target}_PIONEER="{link}"\n', ] for i in range(2022, 2025): releases.append(f'{target}_LEGACY_{i}="{link}"\n') releases.append(f'{target}_LEGACY_{i}_TAG="{year_to_tag[i]}"\n') - else: # predefined - assert(isinstance(link, dict)) + else: # predefined + assert isinstance(link, dict) releases = [ f'{target}_PIONEER="{link[2024]}"\n', ] for i in range(2020, 2025): if isinstance(link[i], str): releases.append(f'{target}_LEGACY_{i}="{link[i]}"\n') - else: # git repo, + tag or commit + else: # git repo, + tag or commit releases.append(f'{target}_LEGACY_{i}="{link[i][0]}"\n') releases.append(f'{target}_LEGACY_{i}_TAG="{link[i][1]}"\n') - with open(path_to_releases, 'w') as f: + with open(path_to_releases, "w") as f: for line in releases: f.write(line) - print(f'Wrote to {path_to_releases}') + print(f"Wrote to {path_to_releases}") # clean -all_repos = ' '.join(repos) -print(f'rm -rf {all_repos}') +all_repos = " ".join(repos) +print(f"rm -rf {all_repos}") diff --git a/targets/libsndfile/build.sh b/targets/libsndfile/build.sh index 89a808d93..0bd34e293 100755 --- a/targets/libsndfile/build.sh +++ b/targets/libsndfile/build.sh @@ -9,12 +9,12 @@ set -e ## if [ ! -d "$TARGET/repo" ]; then - echo "fetch.sh must be executed first." + echo "fetch_target.sh must be executed first." exit 1 fi cd "$TARGET/repo" -./autogen.sh +autoreconf -f -i ./configure --disable-shared --enable-ossfuzzers make -j$(nproc) clean make -j$(nproc) ossfuzz/sndfile_fuzzer diff --git a/targets/libsndfile/fetch.sh b/targets/libsndfile/fetch.sh deleted file mode 100755 index a7cdbd05d..000000000 --- a/targets/libsndfile/fetch.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://github.com/libsndfile/libsndfile.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout 86c9f9eb7022d186ad4d0689487e7d4f04ce2b29 \ No newline at end of file diff --git a/targets/libsndfile/patches/setup/libsndfile.patch b/targets/libsndfile/patches/failed/setup/libsndfile.patch similarity index 100% rename from targets/libsndfile/patches/setup/libsndfile.patch rename to targets/libsndfile/patches/failed/setup/libsndfile.patch diff --git a/targets/libsndfile/releases b/targets/libsndfile/releases new file mode 100644 index 000000000..e8006961c --- /dev/null +++ b/targets/libsndfile/releases @@ -0,0 +1,7 @@ +libsndfile_PIONEER="https://github.com/libsndfile/libsndfile.git" +libsndfile_LEGACY_2022="https://github.com/libsndfile/libsndfile.git" +libsndfile_LEGACY_2022_TAG="1.1.0" +libsndfile_LEGACY_2023="https://github.com/libsndfile/libsndfile.git" +libsndfile_LEGACY_2023_TAG="1.2.1" +libsndfile_LEGACY_2024="https://github.com/libsndfile/libsndfile.git" +libsndfile_LEGACY_2024_TAG="1.2.1" From a0dda279680f55c3e5211d46deb617ce22c5bc52 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 17:30:03 +0100 Subject: [PATCH 012/150] Include gitlab links in fetch_target --- magma/fetch_target.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh index 245d76d03..978c48759 100644 --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -13,7 +13,7 @@ source "$TARGET"/releases to_fetch_var="$TARGET_NAME"_"$TARGET_VERSION" to_fetch=${!to_fetch_var} -if [[ "$to_fetch" =~ ^https://github\.com/.+/.+ ]]; then +if [[ "$to_fetch" =~ ^https://(github\.com|gitlab\.com)/.+/.+ ]]; then git clone "$to_fetch" "$TARGET/repo" elif [[ "$to_fetch" =~ \.tar\.gz$ ]]; then wget -O "$TARGET"/repo.tar.gz "$to_fetch" From 781d0ebdd5c83037a63140ee70729c7b6e2522a3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 17:31:21 +0100 Subject: [PATCH 013/150] Generate libtiff releases --- gen_target_releases.py | 1 + targets/libtiff/releases | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 targets/libtiff/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index 7f2e3caab..69d443239 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -18,6 +18,7 @@ links = { "libpng": "https://github.com/pnggroup/libpng", "libsndfile": "https://github.com/libsndfile/libsndfile.git", + "libtiff": "https://gitlab.com/libtiff/libtiff.git", } repos = [] diff --git a/targets/libtiff/releases b/targets/libtiff/releases new file mode 100644 index 000000000..8b864d88b --- /dev/null +++ b/targets/libtiff/releases @@ -0,0 +1,7 @@ +libtiff_PIONEER="https://gitlab.com/libtiff/libtiff.git" +libtiff_LEGACY_2022="https://gitlab.com/libtiff/libtiff.git" +libtiff_LEGACY_2022_TAG="v3.4beta018" +libtiff_LEGACY_2023="https://gitlab.com/libtiff/libtiff.git" +libtiff_LEGACY_2023_TAG="v4.5.1" +libtiff_LEGACY_2024="https://gitlab.com/libtiff/libtiff.git" +libtiff_LEGACY_2024_TAG="v4.7.0" From 28408cdc5ac83f625d5bc8d65006e8f4b5f0ba56 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 17:31:58 +0100 Subject: [PATCH 014/150] Update build.sh and remove fetch.sh --- targets/libtiff/build.sh | 7 ++++++- targets/libtiff/fetch.sh | 13 ------------- 2 files changed, 6 insertions(+), 14 deletions(-) delete mode 100755 targets/libtiff/fetch.sh diff --git a/targets/libtiff/build.sh b/targets/libtiff/build.sh index fad7e494b..1f5499fa1 100755 --- a/targets/libtiff/build.sh +++ b/targets/libtiff/build.sh @@ -9,10 +9,15 @@ set -e ## if [ ! -d "$TARGET/repo" ]; then - echo "fetch.sh must be executed first." + echo "fetch_target.sh must be executed first." exit 1 fi +# An extra target specific step from previously used libtiff/fetch.sh +# TODO: Are there any changes to be made in this file? +cp "$TARGET/src/tiff_read_rgba_fuzzer.cc" \ + "$TARGET/repo/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc" + WORK="$TARGET/work" rm -rf "$WORK" mkdir -p "$WORK" diff --git a/targets/libtiff/fetch.sh b/targets/libtiff/fetch.sh deleted file mode 100755 index f6e3c7c23..000000000 --- a/targets/libtiff/fetch.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://gitlab.com/libtiff/libtiff.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout c145a6c14978f73bb484c955eb9f84203efcb12e - -cp "$TARGET/src/tiff_read_rgba_fuzzer.cc" \ - "$TARGET/repo/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc" From 0234650dd927e4be8cb40125715650f32e6d7b9f Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 17:32:54 +0100 Subject: [PATCH 015/150] Move libtiff bug patches to failed --- targets/libtiff/patches/{ => failed}/bugs/TIF001.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF002.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF003.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF004.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF005.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF006.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF007.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF008.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF009.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF010.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF011.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF012.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF013.patch | 0 targets/libtiff/patches/{ => failed}/bugs/TIF014.patch | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename targets/libtiff/patches/{ => failed}/bugs/TIF001.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF002.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF003.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF004.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF005.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF006.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF007.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF008.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF009.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF010.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF011.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF012.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF013.patch (100%) rename targets/libtiff/patches/{ => failed}/bugs/TIF014.patch (100%) diff --git a/targets/libtiff/patches/bugs/TIF001.patch b/targets/libtiff/patches/failed/bugs/TIF001.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF001.patch rename to targets/libtiff/patches/failed/bugs/TIF001.patch diff --git a/targets/libtiff/patches/bugs/TIF002.patch b/targets/libtiff/patches/failed/bugs/TIF002.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF002.patch rename to targets/libtiff/patches/failed/bugs/TIF002.patch diff --git a/targets/libtiff/patches/bugs/TIF003.patch b/targets/libtiff/patches/failed/bugs/TIF003.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF003.patch rename to targets/libtiff/patches/failed/bugs/TIF003.patch diff --git a/targets/libtiff/patches/bugs/TIF004.patch b/targets/libtiff/patches/failed/bugs/TIF004.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF004.patch rename to targets/libtiff/patches/failed/bugs/TIF004.patch diff --git a/targets/libtiff/patches/bugs/TIF005.patch b/targets/libtiff/patches/failed/bugs/TIF005.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF005.patch rename to targets/libtiff/patches/failed/bugs/TIF005.patch diff --git a/targets/libtiff/patches/bugs/TIF006.patch b/targets/libtiff/patches/failed/bugs/TIF006.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF006.patch rename to targets/libtiff/patches/failed/bugs/TIF006.patch diff --git a/targets/libtiff/patches/bugs/TIF007.patch b/targets/libtiff/patches/failed/bugs/TIF007.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF007.patch rename to targets/libtiff/patches/failed/bugs/TIF007.patch diff --git a/targets/libtiff/patches/bugs/TIF008.patch b/targets/libtiff/patches/failed/bugs/TIF008.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF008.patch rename to targets/libtiff/patches/failed/bugs/TIF008.patch diff --git a/targets/libtiff/patches/bugs/TIF009.patch b/targets/libtiff/patches/failed/bugs/TIF009.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF009.patch rename to targets/libtiff/patches/failed/bugs/TIF009.patch diff --git a/targets/libtiff/patches/bugs/TIF010.patch b/targets/libtiff/patches/failed/bugs/TIF010.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF010.patch rename to targets/libtiff/patches/failed/bugs/TIF010.patch diff --git a/targets/libtiff/patches/bugs/TIF011.patch b/targets/libtiff/patches/failed/bugs/TIF011.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF011.patch rename to targets/libtiff/patches/failed/bugs/TIF011.patch diff --git a/targets/libtiff/patches/bugs/TIF012.patch b/targets/libtiff/patches/failed/bugs/TIF012.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF012.patch rename to targets/libtiff/patches/failed/bugs/TIF012.patch diff --git a/targets/libtiff/patches/bugs/TIF013.patch b/targets/libtiff/patches/failed/bugs/TIF013.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF013.patch rename to targets/libtiff/patches/failed/bugs/TIF013.patch diff --git a/targets/libtiff/patches/bugs/TIF014.patch b/targets/libtiff/patches/failed/bugs/TIF014.patch similarity index 100% rename from targets/libtiff/patches/bugs/TIF014.patch rename to targets/libtiff/patches/failed/bugs/TIF014.patch From 8a323b379050627c353cf2c92dc81d988291e271 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 25 Feb 2025 17:33:13 +0100 Subject: [PATCH 016/150] Update libtiff setup patch --- targets/libtiff/patches/setup/libtiff.patch | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/targets/libtiff/patches/setup/libtiff.patch b/targets/libtiff/patches/setup/libtiff.patch index 246a3852e..c620f50be 100644 --- a/targets/libtiff/patches/setup/libtiff.patch +++ b/targets/libtiff/patches/setup/libtiff.patch @@ -1,11 +1,15 @@ --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -702,8 +702,6 @@ - add_subdirectory(port) - add_subdirectory(libtiff) - add_subdirectory(tools) --add_subdirectory(test) --add_subdirectory(contrib) +@@ -151,12 +151,6 @@ + if(tiff-tools) + add_subdirectory(tools) + endif() +-if(tiff-tests) +- add_subdirectory(test) +-endif() +-if(tiff-contrib) +- add_subdirectory(contrib) +-endif() add_subdirectory(build) - add_subdirectory(man) - add_subdirectory(html) + if(tiff-docs) + add_subdirectory(doc) From 614c16000c19e4b3389869a2a40ab71b263651a3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 10:58:25 +0100 Subject: [PATCH 017/150] Generate releases libxml --- gen_target_releases.py | 1 + magma/fetch_target.sh | 2 +- targets/libpng/build.sh | 2 +- targets/libxml2/build.sh | 2 +- targets/libxml2/releases | 7 +++++++ 5 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 targets/libxml2/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index 69d443239..d806066be 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -19,6 +19,7 @@ "libpng": "https://github.com/pnggroup/libpng", "libsndfile": "https://github.com/libsndfile/libsndfile.git", "libtiff": "https://gitlab.com/libtiff/libtiff.git", + "libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", } repos = [] diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh index 978c48759..60b0e664c 100644 --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -13,7 +13,7 @@ source "$TARGET"/releases to_fetch_var="$TARGET_NAME"_"$TARGET_VERSION" to_fetch=${!to_fetch_var} -if [[ "$to_fetch" =~ ^https://(github\.com|gitlab\.com)/.+/.+ ]]; then +if [[ "$to_fetch" =~ ^https://(github\.com|gitlab\.com|gitlab\.gnome\.org)/.+/.+ ]]; then git clone "$to_fetch" "$TARGET/repo" elif [[ "$to_fetch" =~ \.tar\.gz$ ]]; then wget -O "$TARGET"/repo.tar.gz "$to_fetch" diff --git a/targets/libpng/build.sh b/targets/libpng/build.sh index 9d2dd0095..4e9af56e9 100755 --- a/targets/libpng/build.sh +++ b/targets/libpng/build.sh @@ -9,7 +9,7 @@ set -e ## if [ ! -d "$TARGET/repo" ]; then - echo "fetch.sh must be executed first." + echo "fetch_target.sh must be executed first." exit 1 fi diff --git a/targets/libxml2/build.sh b/targets/libxml2/build.sh index fb216a882..55e463b1f 100755 --- a/targets/libxml2/build.sh +++ b/targets/libxml2/build.sh @@ -9,7 +9,7 @@ set -e ## if [ ! -d "$TARGET/repo" ]; then - echo "fetch.sh must be executed first." + echo "fetch_target.sh must be executed first." exit 1 fi diff --git a/targets/libxml2/releases b/targets/libxml2/releases new file mode 100644 index 000000000..43e09d983 --- /dev/null +++ b/targets/libxml2/releases @@ -0,0 +1,7 @@ +libxml2_PIONEER="https://gitlab.gnome.org/GNOME/libxml2.git" +libxml2_LEGACY_2022="https://gitlab.gnome.org/GNOME/libxml2.git" +libxml2_LEGACY_2022_TAG="v2.10.0" +libxml2_LEGACY_2023="https://gitlab.gnome.org/GNOME/libxml2.git" +libxml2_LEGACY_2023_TAG="v2.10.4" +libxml2_LEGACY_2024="https://gitlab.gnome.org/GNOME/libxml2.git" +libxml2_LEGACY_2024_TAG="v2.11.7" From 2638db691f05709334f22a99c61f274d0ef3f580 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 10:58:50 +0100 Subject: [PATCH 018/150] Tag automake version libxml --- targets/libxml2/preinstall.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/targets/libxml2/preinstall.sh b/targets/libxml2/preinstall.sh index ca3a3715d..88141a1aa 100755 --- a/targets/libxml2/preinstall.sh +++ b/targets/libxml2/preinstall.sh @@ -1,5 +1,9 @@ #!/bin/bash apt-get update && \ - apt-get install -y git make autoconf automake libtool pkg-config zlib1g-dev \ + apt-get install -y git make autoconf libtool pkg-config zlib1g-dev \ liblzma-dev + +# automake version tagged 10 1.16.3 for latest version of libxml +wget http://ftp.de.debian.org/debian/pool/main/a/automake-1.16/automake_1.16.3-2_all.deb +sudo apt install ./automake_1.16.3-2_all.deb From 37e1558ecfbd1968c141bfaba43465789ded5d17 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 10:59:16 +0100 Subject: [PATCH 019/150] Move patch files libxml --- targets/libxml2/patches/{ => failed}/bugs/XML002.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML003.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML005.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML007.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML008.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML009.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML010.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML011.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML012.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML013.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML014.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML015.patch | 0 targets/libxml2/patches/{ => failed}/bugs/XML017.patch | 0 targets/libxml2/patches/{ => failed}/setup/libxml2.patch | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename targets/libxml2/patches/{ => failed}/bugs/XML002.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML003.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML005.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML007.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML008.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML009.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML010.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML011.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML012.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML013.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML014.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML015.patch (100%) rename targets/libxml2/patches/{ => failed}/bugs/XML017.patch (100%) rename targets/libxml2/patches/{ => failed}/setup/libxml2.patch (100%) diff --git a/targets/libxml2/patches/bugs/XML002.patch b/targets/libxml2/patches/failed/bugs/XML002.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML002.patch rename to targets/libxml2/patches/failed/bugs/XML002.patch diff --git a/targets/libxml2/patches/bugs/XML003.patch b/targets/libxml2/patches/failed/bugs/XML003.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML003.patch rename to targets/libxml2/patches/failed/bugs/XML003.patch diff --git a/targets/libxml2/patches/bugs/XML005.patch b/targets/libxml2/patches/failed/bugs/XML005.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML005.patch rename to targets/libxml2/patches/failed/bugs/XML005.patch diff --git a/targets/libxml2/patches/bugs/XML007.patch b/targets/libxml2/patches/failed/bugs/XML007.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML007.patch rename to targets/libxml2/patches/failed/bugs/XML007.patch diff --git a/targets/libxml2/patches/bugs/XML008.patch b/targets/libxml2/patches/failed/bugs/XML008.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML008.patch rename to targets/libxml2/patches/failed/bugs/XML008.patch diff --git a/targets/libxml2/patches/bugs/XML009.patch b/targets/libxml2/patches/failed/bugs/XML009.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML009.patch rename to targets/libxml2/patches/failed/bugs/XML009.patch diff --git a/targets/libxml2/patches/bugs/XML010.patch b/targets/libxml2/patches/failed/bugs/XML010.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML010.patch rename to targets/libxml2/patches/failed/bugs/XML010.patch diff --git a/targets/libxml2/patches/bugs/XML011.patch b/targets/libxml2/patches/failed/bugs/XML011.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML011.patch rename to targets/libxml2/patches/failed/bugs/XML011.patch diff --git a/targets/libxml2/patches/bugs/XML012.patch b/targets/libxml2/patches/failed/bugs/XML012.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML012.patch rename to targets/libxml2/patches/failed/bugs/XML012.patch diff --git a/targets/libxml2/patches/bugs/XML013.patch b/targets/libxml2/patches/failed/bugs/XML013.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML013.patch rename to targets/libxml2/patches/failed/bugs/XML013.patch diff --git a/targets/libxml2/patches/bugs/XML014.patch b/targets/libxml2/patches/failed/bugs/XML014.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML014.patch rename to targets/libxml2/patches/failed/bugs/XML014.patch diff --git a/targets/libxml2/patches/bugs/XML015.patch b/targets/libxml2/patches/failed/bugs/XML015.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML015.patch rename to targets/libxml2/patches/failed/bugs/XML015.patch diff --git a/targets/libxml2/patches/bugs/XML017.patch b/targets/libxml2/patches/failed/bugs/XML017.patch similarity index 100% rename from targets/libxml2/patches/bugs/XML017.patch rename to targets/libxml2/patches/failed/bugs/XML017.patch diff --git a/targets/libxml2/patches/setup/libxml2.patch b/targets/libxml2/patches/failed/setup/libxml2.patch similarity index 100% rename from targets/libxml2/patches/setup/libxml2.patch rename to targets/libxml2/patches/failed/setup/libxml2.patch From d6b48ecc8e4bb75d861871c987fe150afd9ff32a Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 12:57:27 +0100 Subject: [PATCH 020/150] Update lua to latest version --- gen_target_releases.py | 1 + targets/lua/patches/{ => failed}/bugs/LUA001.patch | 0 targets/lua/patches/{ => failed}/bugs/LUA003.patch | 0 targets/lua/patches/{ => failed}/bugs/LUA004.patch | 0 targets/lua/releases | 7 +++++++ 5 files changed, 8 insertions(+) rename targets/lua/patches/{ => failed}/bugs/LUA001.patch (100%) rename targets/lua/patches/{ => failed}/bugs/LUA003.patch (100%) rename targets/lua/patches/{ => failed}/bugs/LUA004.patch (100%) create mode 100644 targets/lua/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index d806066be..807964c2e 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -20,6 +20,7 @@ "libsndfile": "https://github.com/libsndfile/libsndfile.git", "libtiff": "https://gitlab.com/libtiff/libtiff.git", "libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", + "lua": "https://github.com/lua/lua.git", } repos = [] diff --git a/targets/lua/patches/bugs/LUA001.patch b/targets/lua/patches/failed/bugs/LUA001.patch similarity index 100% rename from targets/lua/patches/bugs/LUA001.patch rename to targets/lua/patches/failed/bugs/LUA001.patch diff --git a/targets/lua/patches/bugs/LUA003.patch b/targets/lua/patches/failed/bugs/LUA003.patch similarity index 100% rename from targets/lua/patches/bugs/LUA003.patch rename to targets/lua/patches/failed/bugs/LUA003.patch diff --git a/targets/lua/patches/bugs/LUA004.patch b/targets/lua/patches/failed/bugs/LUA004.patch similarity index 100% rename from targets/lua/patches/bugs/LUA004.patch rename to targets/lua/patches/failed/bugs/LUA004.patch diff --git a/targets/lua/releases b/targets/lua/releases new file mode 100644 index 000000000..6dc7ef216 --- /dev/null +++ b/targets/lua/releases @@ -0,0 +1,7 @@ +lua_PIONEER="https://github.com/lua/lua.git" +lua_LEGACY_2022="https://github.com/lua/lua.git" +lua_LEGACY_2022_TAG="v5.4.4" +lua_LEGACY_2023="https://github.com/lua/lua.git" +lua_LEGACY_2023_TAG="v5.4.5" +lua_LEGACY_2024="https://github.com/lua/lua.git" +lua_LEGACY_2024_TAG="v5.4.7" From ed38f09b5c298705cddf8d5134d25aaae33b6106 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 13:02:13 +0100 Subject: [PATCH 021/150] Generate openssl releases --- gen_target_releases.py | 3 ++- targets/libpng/releases | 8 ++++---- targets/lua/fetch.sh | 9 --------- targets/openssl/releases | 7 +++++++ 4 files changed, 13 insertions(+), 14 deletions(-) delete mode 100755 targets/lua/fetch.sh create mode 100644 targets/openssl/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index 807964c2e..db0d62fa0 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -16,11 +16,12 @@ from datetime import datetime links = { - "libpng": "https://github.com/pnggroup/libpng", + "libpng": "https://github.com/pnggroup/libpng.git", "libsndfile": "https://github.com/libsndfile/libsndfile.git", "libtiff": "https://gitlab.com/libtiff/libtiff.git", "libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", "lua": "https://github.com/lua/lua.git", + "openssl": "https://github.com/openssl/openssl.git", } repos = [] diff --git a/targets/libpng/releases b/targets/libpng/releases index 53026fac8..d42d0a407 100644 --- a/targets/libpng/releases +++ b/targets/libpng/releases @@ -1,7 +1,7 @@ -libpng_PIONEER="https://github.com/pnggroup/libpng" -libpng_LEGACY_2022="https://github.com/pnggroup/libpng" +libpng_PIONEER="https://github.com/pnggroup/libpng.git" +libpng_LEGACY_2022="https://github.com/pnggroup/libpng.git" libpng_LEGACY_2022_TAG="v1.6.38" -libpng_LEGACY_2023="https://github.com/pnggroup/libpng" +libpng_LEGACY_2023="https://github.com/pnggroup/libpng.git" libpng_LEGACY_2023_TAG="v1.6.40" -libpng_LEGACY_2024="https://github.com/pnggroup/libpng" +libpng_LEGACY_2024="https://github.com/pnggroup/libpng.git" libpng_LEGACY_2024_TAG="v1.6.41" diff --git a/targets/lua/fetch.sh b/targets/lua/fetch.sh deleted file mode 100755 index 8a42e3976..000000000 --- a/targets/lua/fetch.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://github.com/lua/lua.git "$TARGET/repo" -git -C "$TARGET/repo" checkout dbdc74dc5502c2e05e1c1e2ac894943f418c8431 \ No newline at end of file diff --git a/targets/openssl/releases b/targets/openssl/releases new file mode 100644 index 000000000..67e86b1fc --- /dev/null +++ b/targets/openssl/releases @@ -0,0 +1,7 @@ +openssl_PIONEER="https://github.com/openssl/openssl.git" +openssl_LEGACY_2022="https://github.com/openssl/openssl.git" +openssl_LEGACY_2022_TAG="OpenSSL_1_1_1n" +openssl_LEGACY_2023="https://github.com/openssl/openssl.git" +openssl_LEGACY_2023_TAG="OpenSSL_1_1_1t" +openssl_LEGACY_2024="https://github.com/openssl/openssl.git" +openssl_LEGACY_2024_TAG="openssl-3.0.13" From 0074798696459423a7c1b13d7fbec11f89911083 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 26 Feb 2025 13:16:01 +0100 Subject: [PATCH 022/150] Update openssl version to latest --- targets/openssl/build.sh | 3 +++ targets/openssl/fetch.sh | 12 ------------ .../openssl/patches/{ => failed}/bugs/SSL008.patch | 0 .../openssl/patches/{ => failed}/bugs/SSL015.patch | 0 .../openssl/patches/{ => failed}/bugs/SSL019.patch | 0 .../openssl/patches/{ => failed}/bugs/SSL020.patch | 0 6 files changed, 3 insertions(+), 12 deletions(-) delete mode 100755 targets/openssl/fetch.sh rename targets/openssl/patches/{ => failed}/bugs/SSL008.patch (100%) rename targets/openssl/patches/{ => failed}/bugs/SSL015.patch (100%) rename targets/openssl/patches/{ => failed}/bugs/SSL019.patch (100%) rename targets/openssl/patches/{ => failed}/bugs/SSL020.patch (100%) diff --git a/targets/openssl/build.sh b/targets/openssl/build.sh index 965f44cfe..d14fed12c 100755 --- a/targets/openssl/build.sh +++ b/targets/openssl/build.sh @@ -13,6 +13,9 @@ if [ ! -d "$TARGET/repo" ]; then exit 1 fi +# An extra target specific step from previously used openssl/fetch.sh +cp "$TARGET/src/abilist.txt" "$TARGET/repo/abilist.txt" + # build the libpng library cd "$TARGET/repo" diff --git a/targets/openssl/fetch.sh b/targets/openssl/fetch.sh deleted file mode 100755 index 10e48e47b..000000000 --- a/targets/openssl/fetch.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://github.com/openssl/openssl.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout 3bd5319b5d0df9ecf05c8baba2c401ad8e3ba130 - -cp "$TARGET/src/abilist.txt" "$TARGET/repo/abilist.txt" diff --git a/targets/openssl/patches/bugs/SSL008.patch b/targets/openssl/patches/failed/bugs/SSL008.patch similarity index 100% rename from targets/openssl/patches/bugs/SSL008.patch rename to targets/openssl/patches/failed/bugs/SSL008.patch diff --git a/targets/openssl/patches/bugs/SSL015.patch b/targets/openssl/patches/failed/bugs/SSL015.patch similarity index 100% rename from targets/openssl/patches/bugs/SSL015.patch rename to targets/openssl/patches/failed/bugs/SSL015.patch diff --git a/targets/openssl/patches/bugs/SSL019.patch b/targets/openssl/patches/failed/bugs/SSL019.patch similarity index 100% rename from targets/openssl/patches/bugs/SSL019.patch rename to targets/openssl/patches/failed/bugs/SSL019.patch diff --git a/targets/openssl/patches/bugs/SSL020.patch b/targets/openssl/patches/failed/bugs/SSL020.patch similarity index 100% rename from targets/openssl/patches/bugs/SSL020.patch rename to targets/openssl/patches/failed/bugs/SSL020.patch From cef517082caa051f5c0a3f7ccee524a6cb4f6b1f Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 11 Apr 2025 10:41:09 +0200 Subject: [PATCH 023/150] Categorize failed patched for PHP --- targets/poppler/patches/{ => failed}/bugs/PDF002.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF003.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF004.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF006.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF007.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF009.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF015.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF017.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF018.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF019.patch | 0 targets/poppler/patches/{ => failed}/bugs/PDF022.patch | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename targets/poppler/patches/{ => failed}/bugs/PDF002.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF003.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF004.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF006.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF007.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF009.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF015.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF017.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF018.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF019.patch (100%) rename targets/poppler/patches/{ => failed}/bugs/PDF022.patch (100%) diff --git a/targets/poppler/patches/bugs/PDF002.patch b/targets/poppler/patches/failed/bugs/PDF002.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF002.patch rename to targets/poppler/patches/failed/bugs/PDF002.patch diff --git a/targets/poppler/patches/bugs/PDF003.patch b/targets/poppler/patches/failed/bugs/PDF003.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF003.patch rename to targets/poppler/patches/failed/bugs/PDF003.patch diff --git a/targets/poppler/patches/bugs/PDF004.patch b/targets/poppler/patches/failed/bugs/PDF004.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF004.patch rename to targets/poppler/patches/failed/bugs/PDF004.patch diff --git a/targets/poppler/patches/bugs/PDF006.patch b/targets/poppler/patches/failed/bugs/PDF006.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF006.patch rename to targets/poppler/patches/failed/bugs/PDF006.patch diff --git a/targets/poppler/patches/bugs/PDF007.patch b/targets/poppler/patches/failed/bugs/PDF007.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF007.patch rename to targets/poppler/patches/failed/bugs/PDF007.patch diff --git a/targets/poppler/patches/bugs/PDF009.patch b/targets/poppler/patches/failed/bugs/PDF009.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF009.patch rename to targets/poppler/patches/failed/bugs/PDF009.patch diff --git a/targets/poppler/patches/bugs/PDF015.patch b/targets/poppler/patches/failed/bugs/PDF015.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF015.patch rename to targets/poppler/patches/failed/bugs/PDF015.patch diff --git a/targets/poppler/patches/bugs/PDF017.patch b/targets/poppler/patches/failed/bugs/PDF017.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF017.patch rename to targets/poppler/patches/failed/bugs/PDF017.patch diff --git a/targets/poppler/patches/bugs/PDF018.patch b/targets/poppler/patches/failed/bugs/PDF018.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF018.patch rename to targets/poppler/patches/failed/bugs/PDF018.patch diff --git a/targets/poppler/patches/bugs/PDF019.patch b/targets/poppler/patches/failed/bugs/PDF019.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF019.patch rename to targets/poppler/patches/failed/bugs/PDF019.patch diff --git a/targets/poppler/patches/bugs/PDF022.patch b/targets/poppler/patches/failed/bugs/PDF022.patch similarity index 100% rename from targets/poppler/patches/bugs/PDF022.patch rename to targets/poppler/patches/failed/bugs/PDF022.patch From bf48db2f651a931f9861182d57a7da95793dc40c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 11 Apr 2025 10:41:31 +0200 Subject: [PATCH 024/150] Categorize failed patches for poppler --- targets/php/patches/{ => failed}/bugs/PHP010.patch | 0 targets/php/patches/{ => failed}/bugs/PHP012.patch | 0 targets/php/patches/{ => failed}/bugs/PHP015.patch | 0 targets/php/patches/{ => failed}/setup/setup.patch | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename targets/php/patches/{ => failed}/bugs/PHP010.patch (100%) rename targets/php/patches/{ => failed}/bugs/PHP012.patch (100%) rename targets/php/patches/{ => failed}/bugs/PHP015.patch (100%) rename targets/php/patches/{ => failed}/setup/setup.patch (100%) diff --git a/targets/php/patches/bugs/PHP010.patch b/targets/php/patches/failed/bugs/PHP010.patch similarity index 100% rename from targets/php/patches/bugs/PHP010.patch rename to targets/php/patches/failed/bugs/PHP010.patch diff --git a/targets/php/patches/bugs/PHP012.patch b/targets/php/patches/failed/bugs/PHP012.patch similarity index 100% rename from targets/php/patches/bugs/PHP012.patch rename to targets/php/patches/failed/bugs/PHP012.patch diff --git a/targets/php/patches/bugs/PHP015.patch b/targets/php/patches/failed/bugs/PHP015.patch similarity index 100% rename from targets/php/patches/bugs/PHP015.patch rename to targets/php/patches/failed/bugs/PHP015.patch diff --git a/targets/php/patches/setup/setup.patch b/targets/php/patches/failed/setup/setup.patch similarity index 100% rename from targets/php/patches/setup/setup.patch rename to targets/php/patches/failed/setup/setup.patch From ec50eff3f94503c368811109d80e1c907357696c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 11 Apr 2025 10:42:31 +0200 Subject: [PATCH 025/150] Generate releases for PHP and poppler --- gen_target_releases.py | 2 ++ targets/php/releases | 7 +++++++ targets/poppler/releases | 7 +++++++ 3 files changed, 16 insertions(+) create mode 100644 targets/php/releases create mode 100644 targets/poppler/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index db0d62fa0..d6a63979d 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -22,6 +22,8 @@ "libxml2": "https://gitlab.gnome.org/GNOME/libxml2.git", "lua": "https://github.com/lua/lua.git", "openssl": "https://github.com/openssl/openssl.git", + "php": "https://github.com/php/php-src.git", + "poppler": "https://gitlab.freedesktop.org/poppler/poppler.git", } repos = [] diff --git a/targets/php/releases b/targets/php/releases new file mode 100644 index 000000000..2ef0dbfbc --- /dev/null +++ b/targets/php/releases @@ -0,0 +1,7 @@ +php_PIONEER="https://github.com/php/php-src.git" +php_LEGACY_2022="https://github.com/php/php-src.git" +php_LEGACY_2022_TAG="php-7.4.28" +php_LEGACY_2023="https://github.com/php/php-src.git" +php_LEGACY_2023_TAG="php-8.0.27" +php_LEGACY_2024="https://github.com/php/php-src.git" +php_LEGACY_2024_TAG="php-8.1.28" diff --git a/targets/poppler/releases b/targets/poppler/releases new file mode 100644 index 000000000..980d4d721 --- /dev/null +++ b/targets/poppler/releases @@ -0,0 +1,7 @@ +poppler_PIONEER="https://gitlab.freedesktop.org/poppler/poppler.git" +poppler_LEGACY_2022="https://gitlab.freedesktop.org/poppler/poppler.git" +poppler_LEGACY_2022_TAG="poppler-22.01.0" +poppler_LEGACY_2023="https://gitlab.freedesktop.org/poppler/poppler.git" +poppler_LEGACY_2023_TAG="poppler-23.01.0" +poppler_LEGACY_2024="https://gitlab.freedesktop.org/poppler/poppler.git" +poppler_LEGACY_2024_TAG="poppler-24.01.0" From 951d8f66cb48f6642db093b0d06d3e35f3802578 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 11 Apr 2025 11:04:44 +0200 Subject: [PATCH 026/150] Allow curl redirects for sqlite3 to fix existing build --- targets/sqlite3/fetch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/sqlite3/fetch.sh b/targets/sqlite3/fetch.sh index bce98c328..001359de3 100755 --- a/targets/sqlite3/fetch.sh +++ b/targets/sqlite3/fetch.sh @@ -5,7 +5,7 @@ # - env TARGET: path to target work dir ## -curl "https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=8c432642572c8c4b" \ +curl -L "https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=8c432642572c8c4b" \ -o "$OUT/sqlite.tar.gz" && \ mkdir -p "$TARGET/repo" && \ tar -C "$TARGET/repo" --strip-components=1 -xzf "$OUT/sqlite.tar.gz" \ No newline at end of file From 862e8ef795d1e940c7b29e51f756c4d0f4e9f8a4 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 22 Apr 2025 11:55:23 +0200 Subject: [PATCH 027/150] Move libsndfile.patch to graveyard --- .../patches/{failed/setup => graveyard}/libsndfile.patch | 3 +++ 1 file changed, 3 insertions(+) rename targets/libsndfile/patches/{failed/setup => graveyard}/libsndfile.patch (87%) diff --git a/targets/libsndfile/patches/failed/setup/libsndfile.patch b/targets/libsndfile/patches/graveyard/libsndfile.patch similarity index 87% rename from targets/libsndfile/patches/failed/setup/libsndfile.patch rename to targets/libsndfile/patches/graveyard/libsndfile.patch index cd052c765..207772c91 100644 --- a/targets/libsndfile/patches/failed/setup/libsndfile.patch +++ b/targets/libsndfile/patches/graveyard/libsndfile.patch @@ -1,3 +1,6 @@ +// All these updates are already fixed in the latest version of libsndfile. +// This patch is no longer needed. + --- a/Makefile.am +++ b/Makefile.am @@ -450,7 +450,7 @@ From ea0d0189a36b7c8190e29b7cc772d5c95608904d Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 15:51:13 +0200 Subject: [PATCH 028/150] Add step to fetch dependencies in Dockerfile (if present) --- docker/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 0a90410e6..46c2b6814 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -68,8 +68,9 @@ RUN ${TARGET}/preinstall.sh USER magma:magma # TODO: Remove the following line once all targets use fetch_target.sh # RUN ${TARGET}/fetch.sh -RUN chmod +x ${MAGMA}/fetch_target.sh && \ - ${MAGMA}/fetch_target.sh +RUN ${MAGMA}/fetch_target.sh +# Used to fetch any additional git repos for the target +RUN if [ -f ${TARGET}/fetch_deps.sh ]; then /bin/bash ${TARGET}/fetch_deps.sh; fi RUN ${MAGMA}/apply_patches.sh ## Configuration parameters From ba4cd3bdcad4dc75b166f7cfe3b9b6b58708816d Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 16:50:48 +0200 Subject: [PATCH 029/150] Make fetch_target.sh nicer --- magma/fetch_target.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) mode change 100644 => 100755 magma/fetch_target.sh diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh old mode 100644 new mode 100755 index 60b0e664c..09d4d443e --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -13,9 +13,17 @@ source "$TARGET"/releases to_fetch_var="$TARGET_NAME"_"$TARGET_VERSION" to_fetch=${!to_fetch_var} -if [[ "$to_fetch" =~ ^https://(github\.com|gitlab\.com|gitlab\.gnome\.org)/.+/.+ ]]; then +git_hosts=( + github.com + gitlab.com + gitlab.gnome.org + gitlab.freedesktop.org +) +host=$(echo "$to_fetch" | awk -F/ '{print $3}') + +if [[ " ${git_hosts[*]} " == *" $host "* ]]; then git clone "$to_fetch" "$TARGET/repo" -elif [[ "$to_fetch" =~ \.tar\.gz$ ]]; then +elif [[ "$to_fetch" =~ \.tar\.gz(\?|$) ]]; then wget -O "$TARGET"/repo.tar.gz "$to_fetch" mkdir "$TARGET"/repo tar -xf "$TARGET"/repo.tar.gz --strip-components=1 -C "$TARGET"/repo From 41853290fe779c67c4592f0ec5be84b87703146c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 16:52:09 +0200 Subject: [PATCH 030/150] Initial update for scripts in PHP --- targets/php/fetch.sh | 14 -------------- targets/php/fetch_deps.sh | 12 ++++++++++++ targets/php/preinstall.sh | 7 ++++++- 3 files changed, 18 insertions(+), 15 deletions(-) delete mode 100755 targets/php/fetch.sh create mode 100644 targets/php/fetch_deps.sh diff --git a/targets/php/fetch.sh b/targets/php/fetch.sh deleted file mode 100755 index dc3cbd845..000000000 --- a/targets/php/fetch.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://github.com/php/php-src.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout bc39abe8c3c492e29bc5d60ca58442040bbf063b - -git clone --no-checkout https://github.com/kkos/oniguruma.git \ - "$TARGET/repo/oniguruma" -git -C "$TARGET/repo/oniguruma" checkout 227ec0bd690207812793c09ad70024707c405376 \ No newline at end of file diff --git a/targets/php/fetch_deps.sh b/targets/php/fetch_deps.sh new file mode 100644 index 000000000..49e451a01 --- /dev/null +++ b/targets/php/fetch_deps.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +## +# Pre-requirements: +# - env TARGET: path to target work dir +## + + +# Dependency for PHP: oniguruma +git clone https://github.com/kkos/oniguruma.git \ + "$TARGET/repo/oniguruma" diff --git a/targets/php/preinstall.sh b/targets/php/preinstall.sh index 07b1eab7a..23ca73f4d 100755 --- a/targets/php/preinstall.sh +++ b/targets/php/preinstall.sh @@ -1,5 +1,10 @@ #!/bin/bash apt-get update && \ - apt-get install -y git make autoconf automake libtool bison re2c pkg-config \ + apt-get install -y git make autoconf automake libtool bison pkg-config \ libicu-dev + +# Install newer version of re2c needed for build +wget https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz +tar -xzf re2c-1.0.3.tar.gz +cd re2c-1.0.3 && ./configure && make && make install From 9c69ac9430f187f0777e01792188fb43a8c12bbf Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 18:17:33 +0200 Subject: [PATCH 031/150] Add MAGMA_DEBUG feature --- tools/captain/captainrc | 4 ++++ tools/captain/run.sh | 42 ++++++++++++++++++++++++++++++++++++++--- tools/captain/start.sh | 13 +++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/tools/captain/captainrc b/tools/captain/captainrc index 3225690c5..afb0f351d 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -65,6 +65,10 @@ POLL=5 # (default: unset) # POC_EXTRACT=1 +# [MAGMA_DEBUG]: if set, container entrypoint is switched to a shell and fuzzers +# and targets are mounted as volumes. Useful for investigating build issues. +# (default: unset) +# MAGMA_DEBUG=1 ### ## Campaigns to run diff --git a/tools/captain/run.sh b/tools/captain/run.sh index 5d54e90f5..288998063 100755 --- a/tools/captain/run.sh +++ b/tools/captain/run.sh @@ -106,10 +106,19 @@ start_campaign() mkdir -p "$SHARED" && chmod 777 "$SHARED" echo_time "Container $FUZZER/$TARGET/$PROGRAM/$ARCID started on CPU $AFFINITY" - "$MAGMA"/tools/captain/start.sh &> \ - "${LOGDIR}/${FUZZER}_${TARGET}_${PROGRAM}_${ARCID}_container.log" + if [ ! -z "$MAGMA_DEBUG" ]; then + "$MAGMA"/tools/captain/start.sh + else + "$MAGMA"/tools/captain/start.sh &> \ + "${LOGDIR}/${FUZZER}_${TARGET}_${PROGRAM}_${ARCID}_container.log" + fi echo_time "Container $FUZZER/$TARGET/$PROGRAM/$ARCID stopped" + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Skip to extract the PoC." + unset POC_EXTRACT + fi + if [ ! -z $POC_EXTRACT ]; then "$MAGMA"/tools/captain/extract.sh fi @@ -234,11 +243,22 @@ cleanup() trap cleanup EXIT +if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first fuzzer is chosen." + FUZZERS=(${FUZZERS[0]}) +fi + # schedule campaigns for FUZZER in "${FUZZERS[@]}"; do export FUZZER TARGETS=($(get_var_or_default $FUZZER 'TARGETS')) + + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first target is chosen." + TARGETS=(${TARGETS[0]}) + fi + for TARGET in "${TARGETS[@]}"; do export TARGET @@ -254,15 +274,31 @@ for FUZZER in "${FUZZERS[@]}"; do fi PROGRAMS=($(get_var_or_default $FUZZER $TARGET 'PROGRAMS')) + + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first program is chosen." + PROGRAMS=(${PROGRAMS[0]}) + fi + for PROGRAM in "${PROGRAMS[@]}"; do export PROGRAM export ARGS="$(get_var_or_default $FUZZER $TARGET $PROGRAM 'ARGS')" + + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first instance is running." + REPEAT=1 + fi echo_time "Starting campaigns for $PROGRAM $ARGS" for ((i=0; i<$REPEAT; i++)); do export NUMWORKERS="$(get_var_or_default $FUZZER 'CAMPAIGN_WORKERS')" export AFFINITY=$(allocate_workers) - start_ex & + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Don't run start_ex as a daemon." + start_ex + else + start_ex & + fi done done done diff --git a/tools/captain/start.sh b/tools/captain/start.sh index e91a76f50..01b9c7228 100755 --- a/tools/captain/start.sh +++ b/tools/captain/start.sh @@ -42,6 +42,12 @@ if [ ! -z $AFFINITY ]; then flag_aff="--cpuset-cpus=$AFFINITY --env=AFFINITY=$AFFINITY" fi +if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Old entrypoint: $ENTRYPOINT" + ENTRYPOINT="/bin/bash" + echo_time "New entrypoint: $ENTRYPOINT" +fi + if [ ! -z "$ENTRYPOINT" ]; then flag_ep="--entrypoint=$ENTRYPOINT" fi @@ -51,6 +57,13 @@ if [ ! -z "$SHARED" ]; then flag_volume="--volume=$SHARED:/magma_shared" fi + +if [ ! -z "$MAGMA_DEBUG" ]; then + flag_volume+=" --volume=$MAGMA/fuzzers/__base:/magma/fuzzers/__base" + flag_volume+=" --volume=$MAGMA/fuzzers/$FUZZER:/magma/fuzzers/$FUZZER" + flag_volume+=" --volume=$MAGMA/targets/$TARGET:/magma/targets/$TARGET" +fi + if [ -t 1 ]; then docker run -it $flag_volume \ --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \ From 307a6cce07ecdc04f00c7f44531368ec63838319 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 18:17:54 +0200 Subject: [PATCH 032/150] Allow magma user to use sudo --- docker/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/Dockerfile b/docker/Dockerfile index 46c2b6814..1b124d409 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -30,6 +30,7 @@ RUN mkdir -p /home && \ useradd -l -u ${USER_ID} -K UMASK=0000 -d /home -g magma magma && \ chown magma:magma /home RUN echo "magma:amgam" | chpasswd && usermod -a -G sudo magma +RUN echo "magma ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers RUN mkdir -p ${SHARED} ${OUT} && \ chown magma:magma ${SHARED} ${OUT} && \ From 58003080e28f301460783178bebc986b950c35d3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 18:25:53 +0200 Subject: [PATCH 033/150] Replace legacy ENV whitespace usage with = --- docker/Dockerfile | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1b124d409..6c299c97a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,17 +11,17 @@ RUN apt-get update && apt-get install -y sudo ARG magma_root=./ ## Path variables inside the container -ENV MAGMA_R /magma -ENV OUT /magma_out -ENV SHARED /magma_shared +ENV MAGMA_R=/magma +ENV OUT=/magma_out +ENV SHARED=/magma_shared -ENV CC /usr/bin/gcc -ENV CXX /usr/bin/g++ -ENV LD /usr/bin/ld -ENV AR /usr/bin/ar -ENV AS /usr/bin/as -ENV NM /usr/bin/nm -ENV RANLIB /usr/bin/ranlib +ENV CC=/usr/bin/gcc +ENV CXX=/usr/bin/g++ +ENV LD=/usr/bin/ld +ENV AR=/usr/bin/ar +ENV AS=/usr/bin/as +ENV NM=/usr/bin/nm +ENV RANLIB=/usr/bin/ranlib ARG USER_ID=1000 ARG GROUP_ID=1000 @@ -37,7 +37,7 @@ RUN mkdir -p ${SHARED} ${OUT} && \ chmod 744 ${SHARED} ${OUT} ARG magma_path=magma -ENV MAGMA ${MAGMA_R}/${magma_path} +ENV MAGMA=${MAGMA_R}/${magma_path} USER root:root RUN mkdir -p ${MAGMA} && chown magma:magma ${MAGMA} COPY --chown=magma:magma ${magma_root}/${magma_path} ${MAGMA}/ @@ -47,7 +47,7 @@ RUN ${MAGMA}/prebuild.sh ARG fuzzer_name ARG fuzzer_path=fuzzers/${fuzzer_name} -ENV FUZZER ${MAGMA_R}/${fuzzer_path} +ENV FUZZER=${MAGMA_R}/${fuzzer_path} USER root:root RUN mkdir -p ${FUZZER} && chown magma:magma ${FUZZER} COPY --chown=magma:magma ${magma_root}/${fuzzer_path} ${FUZZER}/ @@ -58,8 +58,8 @@ RUN ${FUZZER}/build.sh ARG target_name ARG target_path=targets/${target_name} -ENV TARGET_NAME ${target_name} -ENV TARGET ${MAGMA_R}/${target_path} +ENV TARGET_NAME=${target_name} +ENV TARGET=${MAGMA_R}/${target_path} ARG target_version ENV TARGET_VERSION=${target_version} USER root:root @@ -86,11 +86,11 @@ ARG CANARIES_FLAG=${canaries:+-DMAGMA_ENABLE_CANARIES} ARG FIXES_FLAG=${fixes:+-DMAGMA_ENABLE_FIXES} ARG BUILD_FLAGS="-include ${MAGMA}/src/canary.h ${CANARIES_FLAG} ${FIXES_FLAG} ${ISAN_FLAG} ${HARDEN_FLAG} -g -O0" -ENV CFLAGS ${BUILD_FLAGS} -ENV CXXFLAGS ${BUILD_FLAGS} -ENV LIBS -l:magma.o -lrt -ENV LDFLAGS -L"${OUT}" -g +ENV CFLAGS=${BUILD_FLAGS} +ENV CXXFLAGS=${BUILD_FLAGS} +ENV LIBS="-l:magma.o -lrt" +ENV LDFLAGS="-L${OUT} -g" RUN ${FUZZER}/instrument.sh -ENTRYPOINT "${MAGMA}/run.sh" +ENTRYPOINT ["${MAGMA}/run.sh"] From 946d52476f66e687c47feef8dbc8ce15f8206655 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 23 Apr 2025 18:26:10 +0200 Subject: [PATCH 034/150] Remove debug containers after use --- tools/captain/start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/captain/start.sh b/tools/captain/start.sh index 01b9c7228..0cd5a929a 100755 --- a/tools/captain/start.sh +++ b/tools/captain/start.sh @@ -65,7 +65,7 @@ if [ ! -z "$MAGMA_DEBUG" ]; then fi if [ -t 1 ]; then - docker run -it $flag_volume \ + docker run -it --rm $flag_volume \ --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \ --env=PROGRAM="$PROGRAM" --env=ARGS="$ARGS" \ --env=FUZZARGS="$FUZZARGS" --env=POLL="$POLL" --env=TIMEOUT="$TIMEOUT" \ From 968e4bb3c3ddf9742060cc1f12dc30300aefa5fc Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 24 Apr 2025 16:49:43 +0200 Subject: [PATCH 035/150] DEBUG mount to workdir --- tools/captain/captainrc | 5 +++-- tools/captain/start.sh | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/captain/captainrc b/tools/captain/captainrc index afb0f351d..ee264adba 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -65,8 +65,9 @@ POLL=5 # (default: unset) # POC_EXTRACT=1 -# [MAGMA_DEBUG]: if set, container entrypoint is switched to a shell and fuzzers -# and targets are mounted as volumes. Useful for investigating build issues. +# [MAGMA_DEBUG]: if set, container entrypoint is switched to a shell. The fuzzer, +# target and magma folders are mounted as volumes in a separate workdir. Useful +# for investigating build issues. # (default: unset) # MAGMA_DEBUG=1 diff --git a/tools/captain/start.sh b/tools/captain/start.sh index 0cd5a929a..d68ac23a9 100755 --- a/tools/captain/start.sh +++ b/tools/captain/start.sh @@ -59,9 +59,9 @@ fi if [ ! -z "$MAGMA_DEBUG" ]; then - flag_volume+=" --volume=$MAGMA/fuzzers/__base:/magma/fuzzers/__base" - flag_volume+=" --volume=$MAGMA/fuzzers/$FUZZER:/magma/fuzzers/$FUZZER" - flag_volume+=" --volume=$MAGMA/targets/$TARGET:/magma/targets/$TARGET" + flag_volume+=" --volume=$MAGMA/magma:/magma/magma" + flag_volume+=" --volume=$MAGMA/fuzzers/$FUZZER:/magma/fuzzers/$FUZZER/workdir" + flag_volume+=" --volume=$MAGMA/targets/$TARGET:/magma/targets/$TARGET/workdir" fi if [ -t 1 ]; then From 2db788b11452208cf70f25ad7aff4bc34d0895e0 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Apr 2025 00:06:15 +0200 Subject: [PATCH 036/150] Fix entrypoint --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 6c299c97a..3b53d4c83 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -93,4 +93,4 @@ ENV LDFLAGS="-L${OUT} -g" RUN ${FUZZER}/instrument.sh -ENTRYPOINT ["${MAGMA}/run.sh"] +ENTRYPOINT ["/bin/bash", "-c", "${MAGMA}/run.sh"] From 429f50ef9a5e6552724965186d24935332ea30d9 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Apr 2025 00:14:07 +0200 Subject: [PATCH 037/150] Fix setup patch for PHP latest version --- targets/php/patches/failed/setup/setup.patch | 68 -------------------- targets/php/patches/setup/setup.patch | 66 +++++++++++++++++++ 2 files changed, 66 insertions(+), 68 deletions(-) delete mode 100644 targets/php/patches/failed/setup/setup.patch create mode 100644 targets/php/patches/setup/setup.patch diff --git a/targets/php/patches/failed/setup/setup.patch b/targets/php/patches/failed/setup/setup.patch deleted file mode 100644 index c4e1a2282..000000000 --- a/targets/php/patches/failed/setup/setup.patch +++ /dev/null @@ -1,68 +0,0 @@ ---- a/build/php.m4 -+++ b/build/php.m4 -@@ -252,8 +252,9 @@ dnl Append to the array which has been dynamically chosen at m4 time. - dnl Choose the right compiler/flags/etc. for the source-file. - case $ac_src in - *.c[)] ac_comp="$b_c_pre $ac_inc $b_c_meta $3 -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; -- *.s[)] ac_comp="$b_c_pre $ac_inc $b_c_meta $3 -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; -- *.S[)] ac_comp="$b_c_pre $ac_inc $b_c_meta $3 -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; -+ *.s|*.S[)] -+ b_c_meta_clean='$(COMMON_FLAGS) $(CFLAGS_CLEAN)'; -+ ac_comp="$b_c_pre $ac_inc $b_c_meta_clean $3 -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; - *.cpp|*.cc|*.cxx[)] ac_comp="$b_cxx_pre $ac_inc $b_cxx_meta $3 -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;; - esac - ---- a/sapi/fuzzer/config.m4 -+++ b/sapi/fuzzer/config.m4 -@@ -60,7 +60,7 @@ if test "$PHP_FUZZER" != "no"; then - ]) - else - FUZZING_LIB="$LIB_FUZZING_ENGINE" -- FUZZING_CC="$CXX -stdlib=libc++" -+ AX_CHECK_COMPILE_FLAG([-stdlib=libstdc++], [FUZZING_CC="$CXX -stdlib=libstdc++"], [FUZZING_CC="$CXX"]) - fi - PHP_SUBST(FUZZING_LIB) - PHP_SUBST(FUZZING_CC) ---- a/ext/standard/string.c -+++ b/ext/standard/string.c -@@ -3682,10 +3682,14 @@ - # include "Zend/zend_cpuinfo.h" - - ZEND_INTRIN_SSE4_2_FUNC_DECL(zend_string *php_addslashes_sse42(zend_string *str)); -+ -+__attribute__((used)) - zend_string *php_addslashes_default(zend_string *str); - - ZEND_INTRIN_SSE4_2_FUNC_DECL(void php_stripslashes_sse42(zend_string *str)); -+ -+__attribute__((used)) - void php_stripslashes_default(zend_string *str); - - # if ZEND_INTRIN_SSE4_2_FUNC_PROTO - PHPAPI zend_string *php_addslashes(zend_string *str) __attribute__((ifunc("resolve_addslashes"))); ---- a/ext/standard/base64.c -+++ b/ext/standard/base64.c -@@ -376,8 +376,12 @@ - ZEND_INTRIN_SSSE3_FUNC_DECL(zend_string *php_base64_decode_ex_ssse3(const unsigned char *str, size_t length, bool strict)); - # endif - -+ -+__attribute__((used)) - zend_string *php_base64_encode_default(const unsigned char *str, size_t length); -+ -+__attribute__((used)) - zend_string *php_base64_decode_ex_default(const unsigned char *str, size_t length, bool strict); - - # if (ZEND_INTRIN_AVX2_FUNC_PROTO || ZEND_INTRIN_SSSE3_FUNC_PROTO) - PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) __attribute__((ifunc("resolve_base64_encode"))); ---- a/build/php.m4 -+++ b/build/php.m4 -@@ -2638,7 +2638,7 @@ - AC_MSG_CHECKING([for __builtin_cpu_init]) - - AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[ -- return __builtin_cpu_init()? 1 : 0; -+ return (__builtin_cpu_init(), 1) ? 1 : 0; - ]])], [ - have_builtin_cpu_init=1 - AC_MSG_RESULT([yes]) diff --git a/targets/php/patches/setup/setup.patch b/targets/php/patches/setup/setup.patch new file mode 100644 index 000000000..05217e36f --- /dev/null +++ b/targets/php/patches/setup/setup.patch @@ -0,0 +1,66 @@ +diff --git a/build/php.m4 b/build/php.m4 +index 53684cf011..467ee8a968 100644 +--- a/build/php.m4 ++++ b/build/php.m4 +@@ -272,8 +272,9 @@ dnl Append to the array which has been dynamically chosen at m4 time. + dnl Choose the right compiler/flags/etc. for the source-file. + case $ac_src in + *.c[)] ac_comp="$b_c_pre $ac_inc $b_c_meta m4_normalize(m4_expand([$3])) -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; +- *.s[)] ac_comp="$b_c_pre $ac_inc $b_c_meta m4_normalize(m4_expand([$3])) -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; +- *.S[)] ac_comp="$b_c_pre $ac_inc $b_c_meta m4_normalize(m4_expand([$3])) -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; ++ *.s|*.S[)] ++ b_c_meta_clean='$(COMMON_FLAGS) $(CFLAGS_CLEAN)'; ++ ac_comp="$b_c_pre $ac_inc $b_c_meta_clean m4_normalize(m4_expand([$3])) -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_c_post" ;; + *.cpp|*.cc|*.cxx[)] ac_comp="$b_cxx_pre $ac_inc $b_cxx_meta m4_normalize(m4_expand([$3])) -c $ac_srcdir$ac_src -o $ac_bdir$ac_obj.$b_lo $b_cxx_post" ;; + esac + +@@ -2402,7 +2403,7 @@ AC_CACHE_CHECK([for $1], [php_var], + [__builtin_clz], [return $1(1) ? 1 : 0;], + [__builtin_clzl], [return $1(1) ? 1 : 0;], + [__builtin_clzll], [return $1(1) ? 1 : 0;], +- [__builtin_cpu_init], [$1();], ++ [__builtin_cpu_init], [return ($1(), 1) ? 1 : 0;], + [__builtin_cpu_supports], [return $1("sse")? 1 : 0;], + [__builtin_ctzl], [return $1(2L) ? 1 : 0;], + [__builtin_ctzll], [return $1(2LL) ? 1 : 0;], +diff --git a/ext/standard/base64.c b/ext/standard/base64.c +index 8d4feee849..3c0b73a213 100644 +--- a/ext/standard/base64.c ++++ b/ext/standard/base64.c +@@ -403,7 +403,10 @@ ZEND_INTRIN_SSSE3_FUNC_DECL(zend_string *php_base64_encode_ssse3(const unsigned + ZEND_INTRIN_SSSE3_FUNC_DECL(zend_string *php_base64_decode_ex_ssse3(const unsigned char *str, size_t length, bool strict)); + # endif + ++__attribute__((used)) + zend_string *php_base64_encode_default(const unsigned char *str, size_t length, zend_long flags); ++ ++__attribute__((used)) + zend_string *php_base64_decode_ex_default(const unsigned char *str, size_t length, bool strict); + + # if (defined(ZEND_INTRIN_AVX2_FUNC_PROTO) || defined(ZEND_INTRIN_SSSE3_FUNC_PROTO) || defined(BASE64_INTRIN_AVX512_FUNC_PROTO) || defined(BASE64_INTRIN_AVX512_VBMI_FUNC_PROTO)) +diff --git a/ext/standard/string.c b/ext/standard/string.c +index b15a24a098..457f5833eb 100644 +--- a/ext/standard/string.c ++++ b/ext/standard/string.c +@@ -3837,6 +3837,8 @@ PHPAPI zend_string *php_addcslashes(zend_string *str, const char *what, size_t w + # include "Zend/zend_cpuinfo.h" + + ZEND_INTRIN_SSE4_2_FUNC_DECL(zend_string *php_addslashes_sse42(zend_string *str)); ++ ++__attribute__((used)) + zend_string *php_addslashes_default(zend_string *str); + + # ifdef ZEND_INTRIN_SSE4_2_FUNC_PROTO +diff --git a/sapi/fuzzer/config.m4 b/sapi/fuzzer/config.m4 +index 21a44cd6d8..0bc19cecf0 100644 +--- a/sapi/fuzzer/config.m4 ++++ b/sapi/fuzzer/config.m4 +@@ -42,7 +42,7 @@ if test "$PHP_FUZZER" != "no"; then + [AC_MSG_ERROR([Compiler doesn't support -fsanitize=fuzzer-no-link])]) + ], [ + FUZZING_LIB=$LIB_FUZZING_ENGINE +- FUZZING_CC="$CXX -stdlib=libc++" ++ AX_CHECK_COMPILE_FLAG([-stdlib=libstdc++], [FUZZING_CC="$CXX -stdlib=libstdc++"], [FUZZING_CC="$CXX"]) + ]) + PHP_SUBST([FUZZING_LIB]) + PHP_SUBST([FUZZING_CC]) From 102aa636107ed6c1bce26a708b045c86e4c4266e Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Apr 2025 00:14:55 +0200 Subject: [PATCH 038/150] Fix PHP build for latest version --- targets/php/build.sh | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/targets/php/build.sh b/targets/php/build.sh index 7207c0b8f..0876420c8 100755 --- a/targets/php/build.sh +++ b/targets/php/build.sh @@ -24,8 +24,16 @@ export EXTRA_CXXFLAGS="$CXXFLAGS -fno-sanitize=object-size" unset CFLAGS unset CXXFLAGS +# These need to be exported to build latest PHP with honggfuzz +export CFLAGS="-fPIE" +export CXXFLAGS="-fPIE" +export LDFLAGS="$LDFLAGS -pie" + #build the php library ./buildconf + +# Note: the acv_cv_func_fork=yes is needed to avoid the fork() +# check in configure which fails when using the hongfuzz compiler LIB_FUZZING_ENGINE="-Wall" ./configure \ --disable-all \ --enable-option-checking=fatal \ @@ -37,7 +45,8 @@ LIB_FUZZING_ENGINE="-Wall" ./configure \ --without-pcre-jit \ --disable-phpdbg \ --disable-cgi \ - --with-pic + --with-pic \ + ac_cv_func_fork=yes make -j$(nproc) clean From ec398e17e2227815920e41b1993f0f949197373b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Apr 2025 01:12:24 +0200 Subject: [PATCH 039/150] Move libxml2 setup patch to graveyard --- .../libxml2/patches/{failed/setup => graveyard}/libxml2.patch | 2 ++ 1 file changed, 2 insertions(+) rename targets/libxml2/patches/{failed/setup => graveyard}/libxml2.patch (82%) diff --git a/targets/libxml2/patches/failed/setup/libxml2.patch b/targets/libxml2/patches/graveyard/libxml2.patch similarity index 82% rename from targets/libxml2/patches/failed/setup/libxml2.patch rename to targets/libxml2/patches/graveyard/libxml2.patch index e2faa48c6..2db92bcab 100644 --- a/targets/libxml2/patches/failed/setup/libxml2.patch +++ b/targets/libxml2/patches/graveyard/libxml2.patch @@ -1,3 +1,5 @@ +// No longer needed, XML_COPTS is not used in the updated libxml2 +// anywhere and build is successful without it. diff --git a/Makefile.am b/Makefile.am index 05d1671..75ea675 100644 --- a/Makefile.am From 0c709e4650e28d7ffcbe437d0fb5c38dcb708a13 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Apr 2025 15:10:43 +0200 Subject: [PATCH 040/150] Move LLVM_VER to a variable in AFL++ --- fuzzers/aflplusplus/preinstall.sh | 57 ++++++++++++++++--------------- fuzzers/aflplusplus/run.sh | 1 + 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/fuzzers/aflplusplus/preinstall.sh b/fuzzers/aflplusplus/preinstall.sh index e15163feb..5d786f8db 100755 --- a/fuzzers/aflplusplus/preinstall.sh +++ b/fuzzers/aflplusplus/preinstall.sh @@ -1,35 +1,38 @@ #!/bin/bash set -e +export LLVM_VERSION=9 + apt-get update && \ - apt-get install -y make clang-9 llvm-9-dev libc++-9-dev libc++abi-9-dev \ - build-essential git wget gcc-7-plugin-dev + apt-get install -y make clang-$LLVM_VERSION llvm-$LLVM_VERSION-dev \ + libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev \ + build-essential git wget gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev update-alternatives \ - --install /usr/lib/llvm llvm /usr/lib/llvm-9 20 \ - --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-9 \ - --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-9 \ - --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-9 \ - --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-9 \ - --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-9 \ - --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-9 \ - --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-9 \ - --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-9 \ - --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-9 \ - --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-9 \ - --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-9 \ - --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-9 \ - --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-9 \ - --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-9 \ - --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-9 \ - --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-9 \ - --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-9 \ - --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-9 \ - --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-9 \ - --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-9 \ - --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-9 + --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ + --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-$LLVM_VERSION \ + --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-$LLVM_VERSION \ + --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-$LLVM_VERSION \ + --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ + --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ + --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ + --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ + --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-$LLVM_VERSION \ + --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-$LLVM_VERSION \ + --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-$LLVM_VERSION \ + --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-$LLVM_VERSION \ + --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-$LLVM_VERSION \ + --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-$LLVM_VERSION \ + --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-$LLVM_VERSION \ + --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-$LLVM_VERSION \ + --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-$LLVM_VERSION \ + --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-$LLVM_VERSION \ + --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-$LLVM_VERSION update-alternatives \ - --install /usr/bin/clang clang /usr/bin/clang-9 20 \ - --slave /usr/bin/clang++ clang++ /usr/bin/clang++-9 \ - --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-9 + --install /usr/bin/clang clang /usr/bin/clang-$LLVM_VERSION 20 \ + --slave /usr/bin/clang++ clang++ /usr/bin/clang++-$LLVM_VERSION \ + --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-$LLVM_VERSION diff --git a/fuzzers/aflplusplus/run.sh b/fuzzers/aflplusplus/run.sh index 8a369e3a9..85245aad5 100755 --- a/fuzzers/aflplusplus/run.sh +++ b/fuzzers/aflplusplus/run.sh @@ -24,6 +24,7 @@ export AFL_NO_AFFINITY=1 export AFL_NO_UI=1 export AFL_MAP_SIZE=256000 export AFL_DRIVER_DONT_DEFER=1 +export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 "$FUZZER/repo/afl-fuzz" -i "$TARGET/corpus/$PROGRAM" -o "$SHARED/findings" \ "${flag_cmplog[@]}" -d \ From c5f4c0223db0164fc40c8b74debc043427682a02 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 13:01:36 +0200 Subject: [PATCH 041/150] Fix typo --- targets/openssl/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/openssl/build.sh b/targets/openssl/build.sh index d14fed12c..6bed1e783 100755 --- a/targets/openssl/build.sh +++ b/targets/openssl/build.sh @@ -16,7 +16,7 @@ fi # An extra target specific step from previously used openssl/fetch.sh cp "$TARGET/src/abilist.txt" "$TARGET/repo/abilist.txt" -# build the libpng library +# build the openssl library cd "$TARGET/repo" CONFIGURE_FLAGS="" From 809d8025eaee0cd0af883b218c23bd71ab9c6eed Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 13:02:34 +0200 Subject: [PATCH 042/150] Upgrade honggfuzz clang to 16 --- fuzzers/honggfuzz/preinstall.sh | 61 ++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/fuzzers/honggfuzz/preinstall.sh b/fuzzers/honggfuzz/preinstall.sh index af78a1c09..10e232362 100755 --- a/fuzzers/honggfuzz/preinstall.sh +++ b/fuzzers/honggfuzz/preinstall.sh @@ -1,35 +1,42 @@ #!/bin/bash set -e +# TODO: Ensure that this works for all targets. +export LLVM_VERSION=16 + apt-get update && \ - apt-get install -y make git wget binutils-dev libunwind-dev \ - clang-9 llvm-9-dev build-essential libblocksruntime-dev + apt-get install -y make git wget binutils-dev lsb-release libunwind-dev \ + software-properties-common build-essential libblocksruntime-dev + +add-apt-repository -y ppa:ubuntu-toolchain-r/test +wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh +./llvm.sh $LLVM_VERSION update-alternatives \ - --install /usr/lib/llvm llvm /usr/lib/llvm-9 20 \ - --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-9 \ - --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-9 \ - --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-9 \ - --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-9 \ - --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-9 \ - --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-9 \ - --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-9 \ - --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-9 \ - --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-9 \ - --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-9 \ - --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-9 \ - --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-9 \ - --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-9 \ - --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-9 \ - --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-9 \ - --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-9 \ - --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-9 \ - --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-9 \ - --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-9 \ - --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-9 \ - --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-9 + --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ + --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-$LLVM_VERSION \ + --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-$LLVM_VERSION \ + --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-$LLVM_VERSION \ + --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ + --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ + --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ + --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ + --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-$LLVM_VERSION \ + --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-$LLVM_VERSION \ + --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-$LLVM_VERSION \ + --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-$LLVM_VERSION \ + --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-$LLVM_VERSION \ + --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-$LLVM_VERSION \ + --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-$LLVM_VERSION \ + --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-$LLVM_VERSION \ + --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-$LLVM_VERSION \ + --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-$LLVM_VERSION \ + --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-$LLVM_VERSION update-alternatives \ - --install /usr/bin/clang clang /usr/bin/clang-9 20 \ - --slave /usr/bin/clang++ clang++ /usr/bin/clang++-9 \ - --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-9 \ No newline at end of file + --install /usr/bin/clang clang /usr/bin/clang-$LLVM_VERSION 20 \ + --slave /usr/bin/clang++ clang++ /usr/bin/clang++-$LLVM_VERSION \ + --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-$LLVM_VERSION \ No newline at end of file From 5a7b9a4c5b09935252f388b81bae3c4e5ba60ca1 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 13:03:40 +0200 Subject: [PATCH 043/150] Ensure canary.h is ignored while compiling .S files in targets --- magma/src/canary.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/magma/src/canary.h b/magma/src/canary.h index 572f8b22b..ceb1b03ff 100644 --- a/magma/src/canary.h +++ b/magma/src/canary.h @@ -1,3 +1,4 @@ +#ifndef __ASSEMBLER__ #ifndef CANARY_H_ #define CANARY_H_ #ifdef __cplusplus @@ -21,3 +22,4 @@ extern void magma_log(const char *bug, int condition); } #endif #endif +#endif /* __ASSEMBLER__ */ From 06890e129727b601e8627a630bfa63046b7a535f Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 13:04:28 +0200 Subject: [PATCH 044/150] Update poppler to the latest version --- docker/Dockerfile | 1 + fuzzers/honggfuzz/postinstall.sh | 16 +++++++++++ targets/poppler/build.sh | 43 ++++++++++------------------- targets/poppler/preinstall.sh | 47 +++++++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 32 deletions(-) create mode 100755 fuzzers/honggfuzz/postinstall.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index 3b53d4c83..b134045c6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -55,6 +55,7 @@ RUN ${FUZZER}/preinstall.sh USER magma:magma RUN ${FUZZER}/fetch.sh RUN ${FUZZER}/build.sh +RUN if [ -f ${FUZZER}/postinstall.sh ]; then /bin/bash ${FUZZER}/postinstall.sh; fi ARG target_name ARG target_path=targets/${target_name} diff --git a/fuzzers/honggfuzz/postinstall.sh b/fuzzers/honggfuzz/postinstall.sh new file mode 100755 index 000000000..c9906eddd --- /dev/null +++ b/fuzzers/honggfuzz/postinstall.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +# This postinstall script is needed for installing some additional dependencies for some targets (poppler). +# The reason why this needs to be done after the honggfuzz build is because the libc++ packages from the llvm +# PPA bring in libunwind-16 with them, this breaks the honggfuzz build. These packages could be installed +# in the preinstall for poppler instead but that could break other fuzzers since this is a honggfuzz specific +# dependency. + +# The REAL problem is ubuntu 18.04, and all these issues will go away after a major migration to 20.04. + +export LLVM_VERSION=16 + +# Required PPA is added in the preinstall.sh script by llvm.sh +sudo apt-get install -y \ + libclang-rt-$LLVM_VERSION-dev libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev diff --git a/targets/poppler/build.sh b/targets/poppler/build.sh index 973b39c50..de1eb4465 100755 --- a/targets/poppler/build.sh +++ b/targets/poppler/build.sh @@ -16,25 +16,17 @@ fi export WORK="$TARGET/work" rm -rf "$WORK" mkdir -p "$WORK" -mkdir -p "$WORK/lib" "$WORK/include" - -pushd "$TARGET/freetype2" -./autogen.sh -./configure --prefix="$WORK" --disable-shared PKG_CONFIG_PATH="$WORK/lib/pkgconfig" -make -j$(nproc) clean -make -j$(nproc) -make install - mkdir -p "$WORK/poppler" cd "$WORK/poppler" rm -rf * -EXTRA="" -test -n "$AR" && EXTRA="$EXTRA -DCMAKE_AR=$AR" -test -n "$RANLIB" && EXTRA="$EXTRA -DCMAKE_RANLIB=$RANLIB" - cmake "$TARGET/repo" \ - $EXTRA \ + -DCMAKE_CXX_STANDARD=20 \ + -DCMAKE_CXX_STANDARD_REQUIRED=ON \ + -DCMAKE_CXX_EXTENSIONS=OFF \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS -stdlib=libc++" \ + -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ -DCMAKE_BUILD_TYPE=debug \ -DBUILD_SHARED_LIBS=OFF \ -DFONT_CONFIGURATION=generic \ @@ -44,26 +36,21 @@ cmake "$TARGET/repo" \ -DENABLE_LIBPNG=ON \ -DENABLE_LIBTIFF=ON \ -DENABLE_LIBJPEG=ON \ - -DENABLE_SPLASH=ON \ - -DENABLE_UTILS=ON \ + -DENABLE_BOOST=ON \ -DWITH_Cairo=ON \ - -DENABLE_CMS=none \ + -DENABLE_UTILS=ON \ -DENABLE_LIBCURL=OFF \ -DENABLE_GLIB=OFF \ -DENABLE_GOBJECT_INTROSPECTION=OFF \ -DENABLE_QT5=OFF \ - -DENABLE_LIBCURL=OFF \ - -DWITH_NSS3=OFF \ - -DFREETYPE_INCLUDE_DIRS="$WORK/include/freetype2" \ - -DFREETYPE_LIBRARY="$WORK/lib/libfreetype.a" \ - -DICONV_LIBRARIES="/usr/lib/x86_64-linux-gnu/libc.so" \ - -DCMAKE_EXE_LINKER_FLAGS_INIT="$LIBS" + -DENABLE_QT6=OFF \ + -DENABLE_NSS3=OFF \ + -DENABLE_GPGME=OFF make -j$(nproc) poppler poppler-cpp pdfimages pdftoppm -EXTRA="" cp "$WORK/poppler/utils/"{pdfimages,pdftoppm} "$OUT/" -$CXX $CXXFLAGS -std=c++11 -I"$WORK/poppler/cpp" -I"$TARGET/repo/cpp" \ +$CXX $CXXFLAGS -std=c++20 -stdlib=libc++ \ + -I"$WORK/poppler/cpp" -I"$TARGET/repo/cpp" \ "$TARGET/src/pdf_fuzzer.cc" -o "$OUT/pdf_fuzzer" \ - "$WORK/poppler/cpp/libpoppler-cpp.a" "$WORK/poppler/libpoppler.a" \ - "$WORK/lib/libfreetype.a" $LDFLAGS $LIBS -ljpeg -lz \ - -lopenjp2 -lpng -ltiff -llcms2 -lm -lpthread -pthread + "$WORK/poppler/cpp/libpoppler-cpp.a" "$WORK/poppler/libpoppler.a" "/usr/local/lib/libfreetype.a" \ + $LDFLAGS $LIBS -ljpeg -lz -lopenjp2 -lpng -ltiff -llcms2 -lm -lpthread -pthread diff --git a/targets/poppler/preinstall.sh b/targets/poppler/preinstall.sh index 276002d0a..f198f4ebd 100755 --- a/targets/poppler/preinstall.sh +++ b/targets/poppler/preinstall.sh @@ -1,6 +1,45 @@ #!/bin/bash +set -e -apt-get update && \ - apt-get install -y git make autoconf automake libtool pkg-config cmake \ - zlib1g-dev libjpeg-dev libopenjp2-7-dev libpng-dev libcairo2-dev \ - libtiff-dev liblcms2-dev libboost-dev \ No newline at end of file +apt-get install -y git make autoconf automake libtool pkg-config zlib1g-dev \ + libjpeg-dev libopenjp2-7-dev libpng-dev libpixman-1-dev liblcms2-dev + +wget https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz +tar -xzf cmake-3.28.0-linux-x86_64.tar.gz +mv cmake-3.28.0-linux-x86_64 /opt/cmake-3.28.0 +ln -sf /opt/cmake-3.28.0/bin/* /usr/bin/ +rm cmake-3.28.0-linux-x86_64.tar.gz + +wget https://download.osgeo.org/libtiff/tiff-4.3.0.tar.gz +tar -xf tiff-4.3.0.tar.gz && rm tiff-4.3.0.tar.gz +cd tiff-4.3.0 && \ + ./configure --prefix="/usr/local" --disable-shared --disable-lzma && \ + make -j$(nproc) && sudo make install +cd ../ && rm -r tiff-4.3.0 + +git clone https://gitlab.freedesktop.org/freetype/freetype.git +cd freetype && git checkout 2d1abd3bbb4d2396ed63b3e5accd66724cf62307 && \ + ./autogen.sh && \ + ./configure --prefix="/usr/local" --disable-shared && \ + make -j$(nproc) && \ + sudo make install +cd ../ && rm -r freetype + +# Note: These two libraries increase the build time by a lot. This is because they +# need to be built from source in ubuntu 18.04 to get latest versions. They could be +# removed from here if not needed while setting -DENABLE_BOOST=OFF -DWITH_Cairo=OFF +# in the poppler/build.sh script. +wget https://cairographics.org/releases/cairo-1.16.0.tar.xz +tar -xf cairo-1.16.0.tar.xz && rm cairo-1.16.0.tar.xz +cd cairo-1.16.0 &&\ + ./configure --prefix="/usr/local" --disable-shared && \ + make -j$(nproc) && sudo make install +cd ../ && rm -r cairo-1.16.0 + +wget https://archives.boost.io/release/1.75.0/source/boost_1_75_0.tar.bz2 +tar --bzip2 -xf boost_1_75_0.tar.bz2 +cd boost_1_75_0 && \ + sudo ./bootstrap.sh --prefix=/usr/local --with-toolset=gcc && \ + ./b2 toolset=gcc && \ + ./b2 install +cd ../ && rm -r boost_1_75_0 \ No newline at end of file From e1af77bf5f2b4bc54aff37d75cf74829c65626f3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:17:42 +0200 Subject: [PATCH 045/150] Upgrade afl++ to 4.07c (clang and llvm to 16) --- fuzzers/aflplusplus/fetch.sh | 10 +++++----- fuzzers/aflplusplus/instrument.sh | 1 + fuzzers/aflplusplus/postinstall.sh | 14 ++++++++++++++ fuzzers/aflplusplus/preinstall.sh | 11 +++++++---- 4 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 fuzzers/aflplusplus/postinstall.sh diff --git a/fuzzers/aflplusplus/fetch.sh b/fuzzers/aflplusplus/fetch.sh index 4caa9d481..77d2aba31 100755 --- a/fuzzers/aflplusplus/fetch.sh +++ b/fuzzers/aflplusplus/fetch.sh @@ -7,7 +7,7 @@ set -e ## git clone --no-checkout https://github.com/AFLplusplus/AFLplusplus "$FUZZER/repo" -git -C "$FUZZER/repo" checkout 458eb0813a6f7d63eed97f18696bca8274533123 +git -C "$FUZZER/repo" checkout af8c68a774d0271ae6a2145ac566e1c7024e95d5 # Fix: CMake-based build systems fail with duplicate (of main) or undefined references (of LLVMFuzzerTestOneInput) sed -i '{s/^int main/__attribute__((weak)) &/}' $FUZZER/repo/utils/aflpp_driver/aflpp_driver.c @@ -24,15 +24,15 @@ EOF patch -p1 -d "$FUZZER/repo" << EOF --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c -@@ -53,7 +53,7 @@ - #include "hash.h" +@@ -65,7 +65,7 @@ #endif + // AFL++ shared memory fuzz cases -int __afl_sharedmem_fuzzing = 1; +int __afl_sharedmem_fuzzing = 0; - extern unsigned int * __afl_fuzz_len; + extern unsigned int *__afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; - + @@ -111,7 +111,8 @@ extern unsigned int * __afl_fuzz_len; __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); diff --git a/fuzzers/aflplusplus/instrument.sh b/fuzzers/aflplusplus/instrument.sh index 5fdfd1978..7e30e9614 100755 --- a/fuzzers/aflplusplus/instrument.sh +++ b/fuzzers/aflplusplus/instrument.sh @@ -18,6 +18,7 @@ export LIBS="$LIBS -lc++ -lc++abi $FUZZER/repo/utils/aflpp_driver/libAFLDriver.a # AFL++'s driver is compiled against libc++ export CXXFLAGS="$CXXFLAGS -stdlib=libc++" +export LDFLAGS="$LDFLAGS -stdlib=libc++" # Build the AFL-only instrumented version ( diff --git a/fuzzers/aflplusplus/postinstall.sh b/fuzzers/aflplusplus/postinstall.sh new file mode 100644 index 000000000..f009f520a --- /dev/null +++ b/fuzzers/aflplusplus/postinstall.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +# This postinstall script is needed for installing the latest version additional dependencies for aflplusplus. +# The reason why this needs to be done after the build is because the libc++ packages from the llvm +# PPA bring in libunwind-16 with them and this breaks the aflplusplus build. + +# The REAL problem is ubuntu 18.04, and all these issues will go away after a major migration to 20.04. + +export LLVM_VERSION=16 + +# Required PPA is added in the preinstall.sh script by llvm.sh +sudo apt-get install -y llvm-$LLVM_VERSION-dev \ + libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev \ No newline at end of file diff --git a/fuzzers/aflplusplus/preinstall.sh b/fuzzers/aflplusplus/preinstall.sh index 5d786f8db..6ef66f08d 100755 --- a/fuzzers/aflplusplus/preinstall.sh +++ b/fuzzers/aflplusplus/preinstall.sh @@ -1,12 +1,15 @@ #!/bin/bash set -e -export LLVM_VERSION=9 +export LLVM_VERSION=16 apt-get update && \ - apt-get install -y make clang-$LLVM_VERSION llvm-$LLVM_VERSION-dev \ - libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev \ - build-essential git wget gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev + apt-get install -y make build-essential git wget software-properties-common lsb-release \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libunwind-dev + +add-apt-repository -y ppa:ubuntu-toolchain-r/test +wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh +./llvm.sh $LLVM_VERSION update-alternatives \ --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ From b0314ad8cd03149bd44c000e38f9104b0d021f8b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:18:57 +0200 Subject: [PATCH 046/150] Disable afl++ cmplog with PHP to fix build --- fuzzers/aflplusplus/run.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fuzzers/aflplusplus/run.sh b/fuzzers/aflplusplus/run.sh index 85245aad5..a645289f5 100755 --- a/fuzzers/aflplusplus/run.sh +++ b/fuzzers/aflplusplus/run.sh @@ -17,7 +17,12 @@ fi mkdir -p "$SHARED/findings" -flag_cmplog=(-m none -c "$OUT/cmplog/$PROGRAM") +# TODO: Figure out why cmplog gets stuck infinitely on PHP +if [[ "$TARGET" == */php ]]; then + flag_cmplog=() +else + flag_cmplog=(-m none -c "$OUT/cmplog/$PROGRAM") +fi export AFL_SKIP_CPUFREQ=1 export AFL_NO_AFFINITY=1 From 2fc49c30c296a05b18ae9fe8f37f947b04d2ba1b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:19:11 +0200 Subject: [PATCH 047/150] Clean up tars in PHP --- targets/php/preinstall.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/php/preinstall.sh b/targets/php/preinstall.sh index 23ca73f4d..6d73969c1 100755 --- a/targets/php/preinstall.sh +++ b/targets/php/preinstall.sh @@ -6,5 +6,6 @@ apt-get update && \ # Install newer version of re2c needed for build wget https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz -tar -xzf re2c-1.0.3.tar.gz +tar -xzf re2c-1.0.3.tar.gz && rm re2c-1.0.3.tar.gz cd re2c-1.0.3 && ./configure && make && make install +cd .. && rm -r re2c-1.0.3 From 60bf5807312c7bb3871f42ff138c6111ca3960ef Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:41:23 +0200 Subject: [PATCH 048/150] Classify sqlite3 patches --- targets/sqlite3/patches/{ => failed}/bugs/SQL001.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL002.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL003.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL006.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL007.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL012.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL014.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL015.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL017.patch | 0 targets/sqlite3/patches/{ => failed}/bugs/SQL019.patch | 0 .../patches/{setup => graveyard}/tclexec-ignore-stderr.patch | 3 +++ 11 files changed, 3 insertions(+) rename targets/sqlite3/patches/{ => failed}/bugs/SQL001.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL002.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL003.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL006.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL007.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL012.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL014.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL015.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL017.patch (100%) rename targets/sqlite3/patches/{ => failed}/bugs/SQL019.patch (100%) rename targets/sqlite3/patches/{setup => graveyard}/tclexec-ignore-stderr.patch (72%) diff --git a/targets/sqlite3/patches/bugs/SQL001.patch b/targets/sqlite3/patches/failed/bugs/SQL001.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL001.patch rename to targets/sqlite3/patches/failed/bugs/SQL001.patch diff --git a/targets/sqlite3/patches/bugs/SQL002.patch b/targets/sqlite3/patches/failed/bugs/SQL002.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL002.patch rename to targets/sqlite3/patches/failed/bugs/SQL002.patch diff --git a/targets/sqlite3/patches/bugs/SQL003.patch b/targets/sqlite3/patches/failed/bugs/SQL003.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL003.patch rename to targets/sqlite3/patches/failed/bugs/SQL003.patch diff --git a/targets/sqlite3/patches/bugs/SQL006.patch b/targets/sqlite3/patches/failed/bugs/SQL006.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL006.patch rename to targets/sqlite3/patches/failed/bugs/SQL006.patch diff --git a/targets/sqlite3/patches/bugs/SQL007.patch b/targets/sqlite3/patches/failed/bugs/SQL007.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL007.patch rename to targets/sqlite3/patches/failed/bugs/SQL007.patch diff --git a/targets/sqlite3/patches/bugs/SQL012.patch b/targets/sqlite3/patches/failed/bugs/SQL012.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL012.patch rename to targets/sqlite3/patches/failed/bugs/SQL012.patch diff --git a/targets/sqlite3/patches/bugs/SQL014.patch b/targets/sqlite3/patches/failed/bugs/SQL014.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL014.patch rename to targets/sqlite3/patches/failed/bugs/SQL014.patch diff --git a/targets/sqlite3/patches/bugs/SQL015.patch b/targets/sqlite3/patches/failed/bugs/SQL015.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL015.patch rename to targets/sqlite3/patches/failed/bugs/SQL015.patch diff --git a/targets/sqlite3/patches/bugs/SQL017.patch b/targets/sqlite3/patches/failed/bugs/SQL017.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL017.patch rename to targets/sqlite3/patches/failed/bugs/SQL017.patch diff --git a/targets/sqlite3/patches/bugs/SQL019.patch b/targets/sqlite3/patches/failed/bugs/SQL019.patch similarity index 100% rename from targets/sqlite3/patches/bugs/SQL019.patch rename to targets/sqlite3/patches/failed/bugs/SQL019.patch diff --git a/targets/sqlite3/patches/setup/tclexec-ignore-stderr.patch b/targets/sqlite3/patches/graveyard/tclexec-ignore-stderr.patch similarity index 72% rename from targets/sqlite3/patches/setup/tclexec-ignore-stderr.patch rename to targets/sqlite3/patches/graveyard/tclexec-ignore-stderr.patch index 5c204e7ae..b80fd10d1 100644 --- a/targets/sqlite3/patches/setup/tclexec-ignore-stderr.patch +++ b/targets/sqlite3/patches/graveyard/tclexec-ignore-stderr.patch @@ -1,3 +1,6 @@ +// This was a bug fix for v3.37, it is already fixed in v3.50 so +// the patch is no longer needed. + --- a/tool/mksqlite3h.tcl +++ b/tool/mksqlite3h.tcl @@ -55,7 +55,7 @@ From 6189f0be344b41c8644681abaf4872b215e89e36 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:42:05 +0200 Subject: [PATCH 049/150] Generate releases for sqlite3 --- gen_target_releases.py | 6 ++++-- targets/sqlite3/fetch.sh | 11 ----------- targets/sqlite3/releases | 7 +++++++ 3 files changed, 11 insertions(+), 13 deletions(-) delete mode 100755 targets/sqlite3/fetch.sh create mode 100644 targets/sqlite3/releases diff --git a/gen_target_releases.py b/gen_target_releases.py index d6a63979d..20bab0297 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -10,10 +10,11 @@ import subprocess import sys +from datetime import datetime + subprocess.check_call([sys.executable, "-m", "pip", "install", "gitpython"]) -from git import Repo -from datetime import datetime +from git import Repo # noqa: E402 links = { "libpng": "https://github.com/pnggroup/libpng.git", @@ -24,6 +25,7 @@ "openssl": "https://github.com/openssl/openssl.git", "php": "https://github.com/php/php-src.git", "poppler": "https://gitlab.freedesktop.org/poppler/poppler.git", + "sqlite3": "https://github.com/sqlite/sqlite", } repos = [] diff --git a/targets/sqlite3/fetch.sh b/targets/sqlite3/fetch.sh deleted file mode 100755 index 001359de3..000000000 --- a/targets/sqlite3/fetch.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -curl -L "https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=8c432642572c8c4b" \ - -o "$OUT/sqlite.tar.gz" && \ -mkdir -p "$TARGET/repo" && \ -tar -C "$TARGET/repo" --strip-components=1 -xzf "$OUT/sqlite.tar.gz" \ No newline at end of file diff --git a/targets/sqlite3/releases b/targets/sqlite3/releases new file mode 100644 index 000000000..51af1c6c4 --- /dev/null +++ b/targets/sqlite3/releases @@ -0,0 +1,7 @@ +sqlite3_PIONEER="https://github.com/sqlite/sqlite" +sqlite3_LEGACY_2022="https://github.com/sqlite/sqlite" +sqlite3_LEGACY_2022_TAG="relese" +sqlite3_LEGACY_2023="https://github.com/sqlite/sqlite" +sqlite3_LEGACY_2023_TAG="version-3.41.0" +sqlite3_LEGACY_2024="https://github.com/sqlite/sqlite" +sqlite3_LEGACY_2024_TAG="version-3.44.3" From b7b673b95704746baf56f4eb207e271c86374ee4 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 30 Apr 2025 21:52:14 +0200 Subject: [PATCH 050/150] Fix sqlite3 build --- targets/sqlite3/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/sqlite3/build.sh b/targets/sqlite3/build.sh index 08a3e611c..b650ed288 100755 --- a/targets/sqlite3/build.sh +++ b/targets/sqlite3/build.sh @@ -30,7 +30,7 @@ export CFLAGS="$CFLAGS -DSQLITE_MAX_LENGTH=128000000 \ "$TARGET/repo"/configure --disable-shared --enable-rtree make clean -make -j$(nproc) +make -j$(nproc) LDFLAGS.configure="$LIBS $LDFLAGS" make sqlite3.c $CC $CFLAGS -I. \ From 4a15bd68c764505143041db9f13d739fe5a90cc7 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 2 May 2025 16:14:47 +0200 Subject: [PATCH 051/150] Include pioneer stable commit in gen target releases --- gen_target_releases.py | 24 +++++++++++++++++++++--- targets/libpng/releases | 1 + targets/libsndfile/releases | 1 + targets/libtiff/releases | 1 + targets/libxml2/releases | 1 + targets/lua/releases | 1 + targets/openssl/releases | 1 + targets/php/releases | 1 + targets/poppler/releases | 1 + targets/sqlite3/releases | 1 + 10 files changed, 30 insertions(+), 3 deletions(-) diff --git a/gen_target_releases.py b/gen_target_releases.py index 20bab0297..fcab4e05c 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -31,17 +31,22 @@ repos = [] -def get_tags(repo_url): +def clone_repo(repo_url): repo_name = repo_url.split("/")[-1].replace(".git", "") local_path = os.path.join(os.getcwd(), repo_name) repos.append(local_path) + repo = None if not os.path.exists(local_path): repo = Repo.clone_from(repo_url, local_path) print(f"Cloned {repo_url}") else: repo = Repo(local_path) + return repo + + +def get_tags(repo): # get all tags available year_to_tag = {} for tag in repo.tags: @@ -65,14 +70,27 @@ def get_tags(repo_url): return year_to_tag_sorted +def get_first_commit_of_year(repo, year): + since = f"{year}-01-01" + until = f"{year}-12-31" + commits = list(repo.iter_commits(rev="HEAD", since=since, until=until)) + return commits[-1].hexsha + + for target, link in links.items(): path_to_releases = os.path.join("targets", target, "releases") if isinstance(link, str): # git repo - year_to_tag = get_tags(link) - print(f"Got tags of {target}") + repo = clone_repo(link) + year_to_tag = get_tags(repo) + + latest_year = max(year_to_tag.keys()) + stable_hash = get_first_commit_of_year(repo, latest_year) + + print(f"Got tags and latest commit of {target}") releases = [ f'{target}_PIONEER="{link}"\n', + f'{target}_PIONEER_STABLE_COMMIT="{stable_hash}"\n', ] for i in range(2022, 2025): releases.append(f'{target}_LEGACY_{i}="{link}"\n') diff --git a/targets/libpng/releases b/targets/libpng/releases index d42d0a407..484098e90 100644 --- a/targets/libpng/releases +++ b/targets/libpng/releases @@ -1,4 +1,5 @@ libpng_PIONEER="https://github.com/pnggroup/libpng.git" +libpng_PIONEER_STABLE_COMMIT="6f786ff0f6bf4b971a7159d2b4a95e8a0770892f" libpng_LEGACY_2022="https://github.com/pnggroup/libpng.git" libpng_LEGACY_2022_TAG="v1.6.38" libpng_LEGACY_2023="https://github.com/pnggroup/libpng.git" diff --git a/targets/libsndfile/releases b/targets/libsndfile/releases index e8006961c..3c63c2a5e 100644 --- a/targets/libsndfile/releases +++ b/targets/libsndfile/releases @@ -1,4 +1,5 @@ libsndfile_PIONEER="https://github.com/libsndfile/libsndfile.git" +libsndfile_PIONEER_STABLE_COMMIT="e5ee50fbda1b9049a45fc65d06c34825feb4f237" libsndfile_LEGACY_2022="https://github.com/libsndfile/libsndfile.git" libsndfile_LEGACY_2022_TAG="1.1.0" libsndfile_LEGACY_2023="https://github.com/libsndfile/libsndfile.git" diff --git a/targets/libtiff/releases b/targets/libtiff/releases index 8b864d88b..53c2169fd 100644 --- a/targets/libtiff/releases +++ b/targets/libtiff/releases @@ -1,4 +1,5 @@ libtiff_PIONEER="https://gitlab.com/libtiff/libtiff.git" +libtiff_PIONEER_STABLE_COMMIT="651b14ffa91722bd1815e367c8e7708925057430" libtiff_LEGACY_2022="https://gitlab.com/libtiff/libtiff.git" libtiff_LEGACY_2022_TAG="v3.4beta018" libtiff_LEGACY_2023="https://gitlab.com/libtiff/libtiff.git" diff --git a/targets/libxml2/releases b/targets/libxml2/releases index 43e09d983..34c42cf4f 100644 --- a/targets/libxml2/releases +++ b/targets/libxml2/releases @@ -1,4 +1,5 @@ libxml2_PIONEER="https://gitlab.gnome.org/GNOME/libxml2.git" +libxml2_PIONEER_STABLE_COMMIT="41c10c0cec2ac072897c7d8df0e87fdf4b715586" libxml2_LEGACY_2022="https://gitlab.gnome.org/GNOME/libxml2.git" libxml2_LEGACY_2022_TAG="v2.10.0" libxml2_LEGACY_2023="https://gitlab.gnome.org/GNOME/libxml2.git" diff --git a/targets/lua/releases b/targets/lua/releases index 6dc7ef216..882694791 100644 --- a/targets/lua/releases +++ b/targets/lua/releases @@ -1,4 +1,5 @@ lua_PIONEER="https://github.com/lua/lua.git" +lua_PIONEER_STABLE_COMMIT="7827c40c49d841daca2a40463b8a60f9a113f77e" lua_LEGACY_2022="https://github.com/lua/lua.git" lua_LEGACY_2022_TAG="v5.4.4" lua_LEGACY_2023="https://github.com/lua/lua.git" diff --git a/targets/openssl/releases b/targets/openssl/releases index 67e86b1fc..b47549f44 100644 --- a/targets/openssl/releases +++ b/targets/openssl/releases @@ -1,4 +1,5 @@ openssl_PIONEER="https://github.com/openssl/openssl.git" +openssl_PIONEER_STABLE_COMMIT="32476957ead4151dceaf873306fc7e79cd262812" openssl_LEGACY_2022="https://github.com/openssl/openssl.git" openssl_LEGACY_2022_TAG="OpenSSL_1_1_1n" openssl_LEGACY_2023="https://github.com/openssl/openssl.git" diff --git a/targets/php/releases b/targets/php/releases index 2ef0dbfbc..2e0325e3c 100644 --- a/targets/php/releases +++ b/targets/php/releases @@ -1,4 +1,5 @@ php_PIONEER="https://github.com/php/php-src.git" +php_PIONEER_STABLE_COMMIT="37190df4239cc0b4f93eb02d1748fb35ad02f63f" php_LEGACY_2022="https://github.com/php/php-src.git" php_LEGACY_2022_TAG="php-7.4.28" php_LEGACY_2023="https://github.com/php/php-src.git" diff --git a/targets/poppler/releases b/targets/poppler/releases index 980d4d721..eedbe4582 100644 --- a/targets/poppler/releases +++ b/targets/poppler/releases @@ -1,4 +1,5 @@ poppler_PIONEER="https://gitlab.freedesktop.org/poppler/poppler.git" +poppler_PIONEER_STABLE_COMMIT="221914fb062253b879c9fbf5a58e89330e679313" poppler_LEGACY_2022="https://gitlab.freedesktop.org/poppler/poppler.git" poppler_LEGACY_2022_TAG="poppler-22.01.0" poppler_LEGACY_2023="https://gitlab.freedesktop.org/poppler/poppler.git" diff --git a/targets/sqlite3/releases b/targets/sqlite3/releases index 51af1c6c4..03349ee16 100644 --- a/targets/sqlite3/releases +++ b/targets/sqlite3/releases @@ -1,4 +1,5 @@ sqlite3_PIONEER="https://github.com/sqlite/sqlite" +sqlite3_PIONEER_STABLE_COMMIT="66985fb8fff34b7d46980202b9a245f3bb9db26a" sqlite3_LEGACY_2022="https://github.com/sqlite/sqlite" sqlite3_LEGACY_2022_TAG="relese" sqlite3_LEGACY_2023="https://github.com/sqlite/sqlite" From 50be27f811badca6dc9513c5567991afda6a5117 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 2 May 2025 16:15:23 +0200 Subject: [PATCH 052/150] Move all targets to start of year commit --- magma/fetch_target.sh | 5 +- .../libsndfile/patches/setup/fix_alac.patch | 47 +++++++++++++++++++ .../libtiff/patches/setup/fix_autogen.patch | 17 +++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 targets/libsndfile/patches/setup/fix_alac.patch create mode 100644 targets/libtiff/patches/setup/fix_autogen.patch diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh index 09d4d443e..fde777342 100755 --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -12,6 +12,8 @@ source "$TARGET"/releases to_fetch_var="$TARGET_NAME"_"$TARGET_VERSION" to_fetch=${!to_fetch_var} +to_checkout_var="$TARGET_NAME"_"$TARGET_VERSION"_"STABLE_COMMIT" +to_checkout=${!to_checkout_var} git_hosts=( github.com @@ -22,7 +24,8 @@ git_hosts=( host=$(echo "$to_fetch" | awk -F/ '{print $3}') if [[ " ${git_hosts[*]} " == *" $host "* ]]; then - git clone "$to_fetch" "$TARGET/repo" + git clone --no-checkout "$to_fetch" "$TARGET/repo" + git -C "$TARGET/repo" checkout "$to_checkout" elif [[ "$to_fetch" =~ \.tar\.gz(\?|$) ]]; then wget -O "$TARGET"/repo.tar.gz "$to_fetch" mkdir "$TARGET"/repo diff --git a/targets/libsndfile/patches/setup/fix_alac.patch b/targets/libsndfile/patches/setup/fix_alac.patch new file mode 100644 index 000000000..8b46b6fd9 --- /dev/null +++ b/targets/libsndfile/patches/setup/fix_alac.patch @@ -0,0 +1,47 @@ +diff --git a/src/ALAC/alac_decoder.c b/src/ALAC/alac_decoder.c +index 978919a7..ff77c1ce 100644 +--- a/src/ALAC/alac_decoder.c ++++ b/src/ALAC/alac_decoder.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + #include "alac_codec.h" +@@ -40,10 +41,6 @@ + #include "ALACBitUtilities.h" + #include "EndianPortable.h" + +-typedef enum +-{ false = 0, +- true = 1 +-} bool ; + + // constants/data + const uint32_t kMaxBitDepth = 32 ; // max allowed bit depth is 32 +diff --git a/src/ALAC/alac_encoder.c b/src/ALAC/alac_encoder.c +index 29012f3f..dc7feb57 100644 +--- a/src/ALAC/alac_encoder.c ++++ b/src/ALAC/alac_encoder.c +@@ -32,6 +32,7 @@ + + #include + #include ++#include + #include + + #include "sfendian.h" +@@ -46,11 +47,6 @@ + #include "ALACAudioTypes.h" + #include "EndianPortable.h" + +-typedef enum +-{ +- false = 0, +- true = 1 +-} bool ; + + static void GetConfig (ALAC_ENCODER *p, ALACSpecificConfig * config) ; + diff --git a/targets/libtiff/patches/setup/fix_autogen.patch b/targets/libtiff/patches/setup/fix_autogen.patch new file mode 100644 index 000000000..15441a7bf --- /dev/null +++ b/targets/libtiff/patches/setup/fix_autogen.patch @@ -0,0 +1,17 @@ +diff --git a/autogen.sh b/autogen.sh +index f63dc11d..3d1d0255 100755 +--- a/autogen.sh ++++ b/autogen.sh +@@ -17,11 +17,9 @@ autoconf + for file in config.guess config.sub + do + echo "$0: getting $file..." +- wget -q --timeout=5 -O config/$file.tmp \ ++ wget --timeout=5 -O config/$file.tmp \ + "https://git.savannah.gnu.org/cgit/config.git/plain/${file}" \ + && mv -f config/$file.tmp config/$file \ + && chmod a+x config/$file +- retval=$? + rm -f config/$file.tmp +- test $retval -eq 0 || exit $retval + done From 4984c846b3c67d55a6608eb9e1e6a6f8093106a0 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 13:27:49 +0200 Subject: [PATCH 053/150] Clean up some TODOs --- docker/Dockerfile | 2 -- fuzzers/honggfuzz/preinstall.sh | 1 - targets/libtiff/build.sh | 2 -- 3 files changed, 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b134045c6..4d4f5c08a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -68,8 +68,6 @@ RUN mkdir -p ${TARGET} && chown magma:magma ${TARGET} COPY --chown=magma:magma ${magma_root}/${target_path} ${TARGET}/ RUN ${TARGET}/preinstall.sh USER magma:magma -# TODO: Remove the following line once all targets use fetch_target.sh -# RUN ${TARGET}/fetch.sh RUN ${MAGMA}/fetch_target.sh # Used to fetch any additional git repos for the target RUN if [ -f ${TARGET}/fetch_deps.sh ]; then /bin/bash ${TARGET}/fetch_deps.sh; fi diff --git a/fuzzers/honggfuzz/preinstall.sh b/fuzzers/honggfuzz/preinstall.sh index 10e232362..c9fce5567 100755 --- a/fuzzers/honggfuzz/preinstall.sh +++ b/fuzzers/honggfuzz/preinstall.sh @@ -1,7 +1,6 @@ #!/bin/bash set -e -# TODO: Ensure that this works for all targets. export LLVM_VERSION=16 apt-get update && \ diff --git a/targets/libtiff/build.sh b/targets/libtiff/build.sh index 1f5499fa1..479ec1609 100755 --- a/targets/libtiff/build.sh +++ b/targets/libtiff/build.sh @@ -13,8 +13,6 @@ if [ ! -d "$TARGET/repo" ]; then exit 1 fi -# An extra target specific step from previously used libtiff/fetch.sh -# TODO: Are there any changes to be made in this file? cp "$TARGET/src/tiff_read_rgba_fuzzer.cc" \ "$TARGET/repo/contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc" From 7c505deb2ce9982f3f7677856d17b0534f70254c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 13:28:27 +0200 Subject: [PATCH 054/150] Update libfuzzer clang to 16 --- fuzzers/libfuzzer/preinstall.sh | 65 +++++++++++++++++---------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/fuzzers/libfuzzer/preinstall.sh b/fuzzers/libfuzzer/preinstall.sh index 715b9e2aa..a29feb1e1 100755 --- a/fuzzers/libfuzzer/preinstall.sh +++ b/fuzzers/libfuzzer/preinstall.sh @@ -1,42 +1,45 @@ #!/bin/bash set -e +LLVM_VERSION=16 + apt-get update && \ - apt-get install -y make build-essential wget git + apt-get install -y make build-essential wget lsb-release software-properties-common -apt-get install -y apt-utils apt-transport-https ca-certificates gnupg +add-apt-repository ppa:git-core/ppa +apt-get update && apt-get install -y git -echo deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main >> /etc/apt/sources.list -wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - +add-apt-repository -y ppa:ubuntu-toolchain-r/test +wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh +./llvm.sh $LLVM_VERSION -apt-get update && \ - apt-get install -y clang-11 +apt-get install -y libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev update-alternatives \ - --install /usr/lib/llvm llvm /usr/lib/llvm-11 20 \ - --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-11 \ - --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-11 \ - --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-11 \ - --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-11 \ - --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-11 \ - --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-11 \ - --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-11 \ - --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-11 \ - --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-11 \ - --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-11 \ - --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-11 \ - --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-11 \ - --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-11 \ - --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-11 \ - --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-11 \ - --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-11 \ - --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-11 \ - --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-11 \ - --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-11 \ - --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-11 \ - --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-11 + --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ + --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-$LLVM_VERSION \ + --slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-$LLVM_VERSION \ + --slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-$LLVM_VERSION \ + --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ + --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ + --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ + --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ + --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-$LLVM_VERSION \ + --slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-$LLVM_VERSION \ + --slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-$LLVM_VERSION \ + --slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-$LLVM_VERSION \ + --slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-$LLVM_VERSION \ + --slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-$LLVM_VERSION \ + --slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-$LLVM_VERSION \ + --slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-$LLVM_VERSION \ + --slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-$LLVM_VERSION \ + --slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-$LLVM_VERSION \ + --slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-$LLVM_VERSION \ + --slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-$LLVM_VERSION update-alternatives \ - --install /usr/bin/clang clang /usr/bin/clang-11 20 \ - --slave /usr/bin/clang++ clang++ /usr/bin/clang++-11 \ - --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-11 + --install /usr/bin/clang clang /usr/bin/clang-$LLVM_VERSION 20 \ + --slave /usr/bin/clang++ clang++ /usr/bin/clang++-$LLVM_VERSION \ + --slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-$LLVM_VERSION From afb4330fd167bb74c691db2055b85b70776c7ac0 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 13:28:55 +0200 Subject: [PATCH 055/150] Use libc++ over libstdc++ to build libfuzzer --- fuzzers/libfuzzer/build.sh | 4 ++-- fuzzers/libfuzzer/instrument.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fuzzers/libfuzzer/build.sh b/fuzzers/libfuzzer/build.sh index 740c40c31..243e95175 100755 --- a/fuzzers/libfuzzer/build.sh +++ b/fuzzers/libfuzzer/build.sh @@ -9,8 +9,8 @@ set -e # We need the version of LLVM which has the LLVMFuzzerRunDriver exposed cd "$FUZZER/repo/compiler-rt/lib/fuzzer" for f in *.cpp; do - clang++ -stdlib=libstdc++ -fPIC -O2 -std=c++11 $f -c & + clang++ -stdlib=libc++ -fPIC -O2 -std=c++20 $f -c & done && wait ar r "$OUT/libFuzzer.a" *.o -clang++ $CXXFLAGS -std=c++11 -c "$FUZZER/src/driver.cpp" -fPIC -o "$OUT/driver.o" \ No newline at end of file +clang++ $CXXFLAGS -std=c++20 -c "$FUZZER/src/driver.cpp" -fPIC -o "$OUT/driver.o" \ No newline at end of file diff --git a/fuzzers/libfuzzer/instrument.sh b/fuzzers/libfuzzer/instrument.sh index 8d17752db..8a4371e29 100755 --- a/fuzzers/libfuzzer/instrument.sh +++ b/fuzzers/libfuzzer/instrument.sh @@ -17,7 +17,7 @@ export CFLAGS="$CFLAGS -fsanitize=fuzzer-no-link" export CXXFLAGS="$CXXFLAGS -fsanitize=fuzzer-no-link" export LDFLAGS="$LDFLAGS -fsanitize=fuzzer-no-link" -export LIBS="$LIBS -l:driver.o $OUT/libFuzzer.a -lstdc++" +export LIBS="$LIBS -l:driver.o $OUT/libFuzzer.a -lc++ -lc++abi" "$MAGMA/build.sh" "$TARGET/build.sh" From 5984002bd3a65fad30ba1a98aa0d1cf78c2df568 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 13:29:20 +0200 Subject: [PATCH 056/150] Make libfuzzer fetch more efficient and pull latest --- fuzzers/libfuzzer/fetch.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/fuzzers/libfuzzer/fetch.sh b/fuzzers/libfuzzer/fetch.sh index cea097035..fc85196ee 100755 --- a/fuzzers/libfuzzer/fetch.sh +++ b/fuzzers/libfuzzer/fetch.sh @@ -6,5 +6,19 @@ set -e # - env FUZZER: path to fuzzer work dir ## -git clone --no-checkout https://github.com/llvm/llvm-project.git "$FUZZER/repo" -git -C "$FUZZER/repo" checkout 29cc50e17a6800ca75cd23ed85ae1ddf3e3dcc14 \ No newline at end of file +# This fetch script fetches only the compiler-rt source code from the LLVM project which +# is much more efficient than cloning the entire LLVM project which takes ~12 minutes. +# It needs latest git version to support sparse checkout. + +# Currently points to the first commit of 2025 +COMPLIER_RT_STABLE_HASH=4b577830033066cfd1b2acf4fcf39950678b27bd + +git clone --depth 1 --filter=blob:none --sparse \ + https://github.com/llvm/llvm-project.git "$FUZZER/repo" + +pushd "$FUZZER/repo" +git sparse-checkout init --cone +git sparse-checkout set compiler-rt/lib/fuzzer +git fetch --depth 1 origin $COMPLIER_RT_STABLE_HASH +git checkout $COMPLIER_RT_STABLE_HASH +popd From 5623e6c9ed46746cc3755c4d3cdaeea6ccbd01f3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 22 May 2025 13:37:49 +0200 Subject: [PATCH 057/150] Minor fixe and cleanup --- gen_target_releases.py | 2 +- targets/libxml2/fetch.sh | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100755 targets/libxml2/fetch.sh diff --git a/gen_target_releases.py b/gen_target_releases.py index fcab4e05c..be0d74314 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -14,7 +14,7 @@ subprocess.check_call([sys.executable, "-m", "pip", "install", "gitpython"]) -from git import Repo # noqa: E402 +from git import Repo # type: ignore # noqa: E402 links = { "libpng": "https://github.com/pnggroup/libpng.git", diff --git a/targets/libxml2/fetch.sh b/targets/libxml2/fetch.sh deleted file mode 100755 index cbe48b2c7..000000000 --- a/targets/libxml2/fetch.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - -git clone --no-checkout https://gitlab.gnome.org/GNOME/libxml2.git \ - "$TARGET/repo" -git -C "$TARGET/repo" checkout ec6e3efb06d7b15cf5a2328fabd3845acea4c815 From 3090387408969685e1fedb37443c92d3eeeec2be Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 22 May 2025 14:44:08 +0200 Subject: [PATCH 058/150] Remove fetch_deps.sh in PHP + move cloning onigiruma to preinstall --- docker/Dockerfile | 2 -- targets/php/build.sh | 9 +++++++-- targets/php/fetch_deps.sh | 12 ------------ targets/php/preinstall.sh | 4 ++++ 4 files changed, 11 insertions(+), 16 deletions(-) delete mode 100644 targets/php/fetch_deps.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index 4d4f5c08a..346ae0cd2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -69,8 +69,6 @@ COPY --chown=magma:magma ${magma_root}/${target_path} ${TARGET}/ RUN ${TARGET}/preinstall.sh USER magma:magma RUN ${MAGMA}/fetch_target.sh -# Used to fetch any additional git repos for the target -RUN if [ -f ${TARGET}/fetch_deps.sh ]; then /bin/bash ${TARGET}/fetch_deps.sh; fi RUN ${MAGMA}/apply_patches.sh ## Configuration parameters diff --git a/targets/php/build.sh b/targets/php/build.sh index 0876420c8..efd30a5b5 100755 --- a/targets/php/build.sh +++ b/targets/php/build.sh @@ -13,6 +13,11 @@ if [ ! -d "$TARGET/repo" ]; then exit 1 fi +# The source code of oniguruma is cloned in preinstall.sh. Do a cp + sudo rm +# over mv so that the script has the correct permissions to build oniguruma. +cp -r "$TARGET/oniguruma" "$TARGET/repo/oniguruma" && \ + sudo rm -rf "$TARGET/oniguruma" + cd "$TARGET/repo" export ONIG_CFLAGS="-I$PWD/oniguruma/src" export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a" @@ -32,8 +37,8 @@ export LDFLAGS="$LDFLAGS -pie" #build the php library ./buildconf -# Note: the acv_cv_func_fork=yes is needed to avoid the fork() -# check in configure which fails when using the hongfuzz compiler +# Note: the acv_cv_func_fork=yes is needed to avoid the fork() +# check in configure which fails when using the hongfuzz compiler LIB_FUZZING_ENGINE="-Wall" ./configure \ --disable-all \ --enable-option-checking=fatal \ diff --git a/targets/php/fetch_deps.sh b/targets/php/fetch_deps.sh deleted file mode 100644 index 49e451a01..000000000 --- a/targets/php/fetch_deps.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -e - -## -# Pre-requirements: -# - env TARGET: path to target work dir -## - - -# Dependency for PHP: oniguruma -git clone https://github.com/kkos/oniguruma.git \ - "$TARGET/repo/oniguruma" diff --git a/targets/php/preinstall.sh b/targets/php/preinstall.sh index 6d73969c1..65d669f4c 100755 --- a/targets/php/preinstall.sh +++ b/targets/php/preinstall.sh @@ -9,3 +9,7 @@ wget https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz tar -xzf re2c-1.0.3.tar.gz && rm re2c-1.0.3.tar.gz cd re2c-1.0.3 && ./configure && make && make install cd .. && rm -r re2c-1.0.3 + +# Dependency for PHP: oniguruma +git clone https://github.com/kkos/oniguruma.git \ + "$TARGET/oniguruma" From 3a1721c6c365f4ec378768304cf9a44786a32184 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 22 May 2025 15:01:35 +0200 Subject: [PATCH 059/150] Make fetching targets faster --- magma/fetch_target.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh index fde777342..48aa14164 100755 --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -24,8 +24,11 @@ git_hosts=( host=$(echo "$to_fetch" | awk -F/ '{print $3}') if [[ " ${git_hosts[*]} " == *" $host "* ]]; then - git clone --no-checkout "$to_fetch" "$TARGET/repo" - git -C "$TARGET/repo" checkout "$to_checkout" + git init "$TARGET/repo" + cd "$TARGET/repo" && \ + git remote add origin "$to_fetch" && \ + git fetch --depth 1 origin "$to_checkout" && \ + git checkout "$to_checkout" elif [[ "$to_fetch" =~ \.tar\.gz(\?|$) ]]; then wget -O "$TARGET"/repo.tar.gz "$to_fetch" mkdir "$TARGET"/repo From 42a0efbb3516298fe29aa6feb22b30f14c4130c2 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 23 May 2025 22:21:02 +0200 Subject: [PATCH 060/150] Update Dockerfile to 24.04 --- docker/Dockerfile | 6 +++--- tools/captain/build.sh | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 346ae0cd2..3b4ba505b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:18.04 +FROM ubuntu:24.04 # TODO remove sudo for user "magma" to avoid unwanted priv escalation from # other attack vectors. @@ -23,8 +23,8 @@ ENV AS=/usr/bin/as ENV NM=/usr/bin/nm ENV RANLIB=/usr/bin/ranlib -ARG USER_ID=1000 -ARG GROUP_ID=1000 +ARG USER_ID=1001 +ARG GROUP_ID=1001 RUN mkdir -p /home && \ groupadd -g ${GROUP_ID} magma && \ useradd -l -u ${USER_ID} -K UMASK=0000 -d /home -g magma magma && \ diff --git a/tools/captain/build.sh b/tools/captain/build.sh index 6553b41a2..afa9bb295 100755 --- a/tools/captain/build.sh +++ b/tools/captain/build.sh @@ -46,8 +46,6 @@ docker build -t "$IMG_NAME" \ --build-arg fuzzer_name="$FUZZER" \ --build-arg target_name="$TARGET" \ --build-arg target_version="$TARGET_VERSION" \ - --build-arg USER_ID=$(id -u $USER) \ - --build-arg GROUP_ID=$(id -g $USER) \ $mode_flag $isan_flag $harden_flag \ -f "$MAGMA/docker/Dockerfile" "$MAGMA" set +x From 8c63209188076fe34973680402df4376307e7333 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 23 May 2025 22:22:22 +0200 Subject: [PATCH 061/150] Update afl++ for Ubuntu 24.04 --- fuzzers/aflplusplus/postinstall.sh | 14 -------------- fuzzers/aflplusplus/preinstall.sh | 10 ++++------ 2 files changed, 4 insertions(+), 20 deletions(-) delete mode 100644 fuzzers/aflplusplus/postinstall.sh diff --git a/fuzzers/aflplusplus/postinstall.sh b/fuzzers/aflplusplus/postinstall.sh deleted file mode 100644 index f009f520a..000000000 --- a/fuzzers/aflplusplus/postinstall.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e - -# This postinstall script is needed for installing the latest version additional dependencies for aflplusplus. -# The reason why this needs to be done after the build is because the libc++ packages from the llvm -# PPA bring in libunwind-16 with them and this breaks the aflplusplus build. - -# The REAL problem is ubuntu 18.04, and all these issues will go away after a major migration to 20.04. - -export LLVM_VERSION=16 - -# Required PPA is added in the preinstall.sh script by llvm.sh -sudo apt-get install -y llvm-$LLVM_VERSION-dev \ - libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev \ No newline at end of file diff --git a/fuzzers/aflplusplus/preinstall.sh b/fuzzers/aflplusplus/preinstall.sh index 6ef66f08d..43b4c88e2 100755 --- a/fuzzers/aflplusplus/preinstall.sh +++ b/fuzzers/aflplusplus/preinstall.sh @@ -4,12 +4,10 @@ set -e export LLVM_VERSION=16 apt-get update && \ - apt-get install -y make build-essential git wget software-properties-common lsb-release \ - gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libunwind-dev - -add-apt-repository -y ppa:ubuntu-toolchain-r/test -wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh -./llvm.sh $LLVM_VERSION + apt-get install -y make build-essential git wget \ + clang-$LLVM_VERSION llvm-$LLVM_VERSION-dev \ + libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev \ + gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev update-alternatives \ --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ From 62b9c02c3291d772c1be2a0215044c0161c29715 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 23 May 2025 22:23:05 +0200 Subject: [PATCH 062/150] Update all targets for Ubuntu 24.04 --- targets/libsndfile/preinstall.sh | 2 +- targets/libxml2/preinstall.sh | 6 +---- targets/php/preinstall.sh | 8 +----- targets/poppler/build.sh | 3 ++- targets/poppler/preinstall.sh | 43 ++------------------------------ 5 files changed, 7 insertions(+), 55 deletions(-) diff --git a/targets/libsndfile/preinstall.sh b/targets/libsndfile/preinstall.sh index 5853c68fa..e429a8822 100755 --- a/targets/libsndfile/preinstall.sh +++ b/targets/libsndfile/preinstall.sh @@ -3,4 +3,4 @@ apt-get update && \ apt-get install -y git make autoconf autogen automake build-essential libasound2-dev \ libflac-dev libogg-dev libtool libvorbis-dev libopus-dev libmp3lame-dev \ - libmpg123-dev pkg-config python + libmpg123-dev pkg-config python-is-python3 diff --git a/targets/libxml2/preinstall.sh b/targets/libxml2/preinstall.sh index 88141a1aa..4cb4dec5a 100755 --- a/targets/libxml2/preinstall.sh +++ b/targets/libxml2/preinstall.sh @@ -2,8 +2,4 @@ apt-get update && \ apt-get install -y git make autoconf libtool pkg-config zlib1g-dev \ - liblzma-dev - -# automake version tagged 10 1.16.3 for latest version of libxml -wget http://ftp.de.debian.org/debian/pool/main/a/automake-1.16/automake_1.16.3-2_all.deb -sudo apt install ./automake_1.16.3-2_all.deb + liblzma-dev automake diff --git a/targets/php/preinstall.sh b/targets/php/preinstall.sh index 65d669f4c..77fc59b44 100755 --- a/targets/php/preinstall.sh +++ b/targets/php/preinstall.sh @@ -2,13 +2,7 @@ apt-get update && \ apt-get install -y git make autoconf automake libtool bison pkg-config \ - libicu-dev - -# Install newer version of re2c needed for build -wget https://github.com/skvadrik/re2c/releases/download/1.0.3/re2c-1.0.3.tar.gz -tar -xzf re2c-1.0.3.tar.gz && rm re2c-1.0.3.tar.gz -cd re2c-1.0.3 && ./configure && make && make install -cd .. && rm -r re2c-1.0.3 + libicu-dev re2c # Dependency for PHP: oniguruma git clone https://github.com/kkos/oniguruma.git \ diff --git a/targets/poppler/build.sh b/targets/poppler/build.sh index de1eb4465..b79e61b46 100755 --- a/targets/poppler/build.sh +++ b/targets/poppler/build.sh @@ -27,6 +27,7 @@ cmake "$TARGET/repo" \ -DCMAKE_CXX_FLAGS="$CXXFLAGS -stdlib=libc++" \ -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ + -DFREETYPE_LIBRARY=/usr/lib/x86_64-linux-gnu/libfreetype.so \ -DCMAKE_BUILD_TYPE=debug \ -DBUILD_SHARED_LIBS=OFF \ -DFONT_CONFIGURATION=generic \ @@ -52,5 +53,5 @@ cp "$WORK/poppler/utils/"{pdfimages,pdftoppm} "$OUT/" $CXX $CXXFLAGS -std=c++20 -stdlib=libc++ \ -I"$WORK/poppler/cpp" -I"$TARGET/repo/cpp" \ "$TARGET/src/pdf_fuzzer.cc" -o "$OUT/pdf_fuzzer" \ - "$WORK/poppler/cpp/libpoppler-cpp.a" "$WORK/poppler/libpoppler.a" "/usr/local/lib/libfreetype.a" \ + "$WORK/poppler/cpp/libpoppler-cpp.a" "$WORK/poppler/libpoppler.a" "/usr/lib/x86_64-linux-gnu/libfreetype.so" \ $LDFLAGS $LIBS -ljpeg -lz -lopenjp2 -lpng -ltiff -llcms2 -lm -lpthread -pthread diff --git a/targets/poppler/preinstall.sh b/targets/poppler/preinstall.sh index f198f4ebd..9701de9cc 100755 --- a/targets/poppler/preinstall.sh +++ b/targets/poppler/preinstall.sh @@ -2,44 +2,5 @@ set -e apt-get install -y git make autoconf automake libtool pkg-config zlib1g-dev \ - libjpeg-dev libopenjp2-7-dev libpng-dev libpixman-1-dev liblcms2-dev - -wget https://cmake.org/files/v3.28/cmake-3.28.0-linux-x86_64.tar.gz -tar -xzf cmake-3.28.0-linux-x86_64.tar.gz -mv cmake-3.28.0-linux-x86_64 /opt/cmake-3.28.0 -ln -sf /opt/cmake-3.28.0/bin/* /usr/bin/ -rm cmake-3.28.0-linux-x86_64.tar.gz - -wget https://download.osgeo.org/libtiff/tiff-4.3.0.tar.gz -tar -xf tiff-4.3.0.tar.gz && rm tiff-4.3.0.tar.gz -cd tiff-4.3.0 && \ - ./configure --prefix="/usr/local" --disable-shared --disable-lzma && \ - make -j$(nproc) && sudo make install -cd ../ && rm -r tiff-4.3.0 - -git clone https://gitlab.freedesktop.org/freetype/freetype.git -cd freetype && git checkout 2d1abd3bbb4d2396ed63b3e5accd66724cf62307 && \ - ./autogen.sh && \ - ./configure --prefix="/usr/local" --disable-shared && \ - make -j$(nproc) && \ - sudo make install -cd ../ && rm -r freetype - -# Note: These two libraries increase the build time by a lot. This is because they -# need to be built from source in ubuntu 18.04 to get latest versions. They could be -# removed from here if not needed while setting -DENABLE_BOOST=OFF -DWITH_Cairo=OFF -# in the poppler/build.sh script. -wget https://cairographics.org/releases/cairo-1.16.0.tar.xz -tar -xf cairo-1.16.0.tar.xz && rm cairo-1.16.0.tar.xz -cd cairo-1.16.0 &&\ - ./configure --prefix="/usr/local" --disable-shared && \ - make -j$(nproc) && sudo make install -cd ../ && rm -r cairo-1.16.0 - -wget https://archives.boost.io/release/1.75.0/source/boost_1_75_0.tar.bz2 -tar --bzip2 -xf boost_1_75_0.tar.bz2 -cd boost_1_75_0 && \ - sudo ./bootstrap.sh --prefix=/usr/local --with-toolset=gcc && \ - ./b2 toolset=gcc && \ - ./b2 install -cd ../ && rm -r boost_1_75_0 \ No newline at end of file + libjpeg-dev libopenjp2-7-dev libpng-dev libpixman-1-dev liblcms2-dev \ + cmake libtiff-dev libboost-dev libcairo2-dev libfreetype6 libfreetype6-dev From fd86685bb41e203488ade81a77edb74a59cfcbd4 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 23 May 2025 23:38:38 +0200 Subject: [PATCH 063/150] Tag afl++ to 2025 commit --- fuzzers/aflplusplus/fetch.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fuzzers/aflplusplus/fetch.sh b/fuzzers/aflplusplus/fetch.sh index 77d2aba31..810a1a455 100755 --- a/fuzzers/aflplusplus/fetch.sh +++ b/fuzzers/aflplusplus/fetch.sh @@ -6,8 +6,11 @@ set -e # - env FUZZER: path to fuzzer work dir ## +# Currently points to the first commit of 2025 +AFLPLUSPLUS_STABLE_HASH=1ddfb1fec2b8aa99886a5de35c07e8f2a7bd8b98 + git clone --no-checkout https://github.com/AFLplusplus/AFLplusplus "$FUZZER/repo" -git -C "$FUZZER/repo" checkout af8c68a774d0271ae6a2145ac566e1c7024e95d5 +git -C "$FUZZER/repo" checkout $AFLPLUSPLUS_STABLE_HASH # Fix: CMake-based build systems fail with duplicate (of main) or undefined references (of LLVMFuzzerTestOneInput) sed -i '{s/^int main/__attribute__((weak)) &/}' $FUZZER/repo/utils/aflpp_driver/aflpp_driver.c From 00f4d52feadf5cc8e0770bb5158bd8fa34b82870 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 09:11:26 +0200 Subject: [PATCH 064/150] Update honggfuzz for Ubuntu 24.04 --- fuzzers/honggfuzz/fetch.sh | 21 ++++----------------- fuzzers/honggfuzz/postinstall.sh | 3 --- fuzzers/honggfuzz/preinstall.sh | 10 +++------- targets/libxml2/build.sh | 2 +- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/fuzzers/honggfuzz/fetch.sh b/fuzzers/honggfuzz/fetch.sh index 5307403d7..ad4e461cc 100755 --- a/fuzzers/honggfuzz/fetch.sh +++ b/fuzzers/honggfuzz/fetch.sh @@ -6,21 +6,8 @@ set -e # - env FUZZER: path to fuzzer work dir ## -git clone --no-checkout https://github.com/google/honggfuzz.git "$FUZZER/repo" -git -C "$FUZZER/repo" checkout fc6b818c1276056bc565d07edec6ada784cd1670 +# Currently points to the first commit of 2025 +HONGGFUZZ_STABLE_HASH=974db6a90f0efcf6b1171cf355a960fed7b1302d -patch -p1 -d "$FUZZER/repo" << EOF ---- a/linux/trace.c -+++ b/linux/trace.c -@@ -232,8 +232,8 @@ struct user_regs_struct { - #endif /* defined(__ANDROID__) */ - - #if defined(__clang__) --_Pragma("clang Diagnostic push\n"); --_Pragma("clang Diagnostic ignored \"-Woverride-init\"\n"); -+_Pragma("clang diagnostic push\n"); -+_Pragma("clang diagnostic ignored \"-Woverride-init\""); - #endif - - static struct { -EOF +git clone --no-checkout https://github.com/google/honggfuzz.git "$FUZZER/repo" +git -C "$FUZZER/repo" checkout $HONGGFUZZ_STABLE_HASH diff --git a/fuzzers/honggfuzz/postinstall.sh b/fuzzers/honggfuzz/postinstall.sh index c9906eddd..6fb2c5594 100755 --- a/fuzzers/honggfuzz/postinstall.sh +++ b/fuzzers/honggfuzz/postinstall.sh @@ -7,10 +7,7 @@ set -e # in the preinstall for poppler instead but that could break other fuzzers since this is a honggfuzz specific # dependency. -# The REAL problem is ubuntu 18.04, and all these issues will go away after a major migration to 20.04. - export LLVM_VERSION=16 -# Required PPA is added in the preinstall.sh script by llvm.sh sudo apt-get install -y \ libclang-rt-$LLVM_VERSION-dev libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev diff --git a/fuzzers/honggfuzz/preinstall.sh b/fuzzers/honggfuzz/preinstall.sh index c9fce5567..2a464a5a9 100755 --- a/fuzzers/honggfuzz/preinstall.sh +++ b/fuzzers/honggfuzz/preinstall.sh @@ -4,13 +4,9 @@ set -e export LLVM_VERSION=16 apt-get update && \ - apt-get install -y make git wget binutils-dev lsb-release libunwind-dev \ - software-properties-common build-essential libblocksruntime-dev - -add-apt-repository -y ppa:ubuntu-toolchain-r/test -wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh -./llvm.sh $LLVM_VERSION - + apt-get install -y make git wget binutils-dev build-essential \ + libblocksruntime-dev libunwind-dev clang-$LLVM_VERSION + update-alternatives \ --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ --slave /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-$LLVM_VERSION \ diff --git a/targets/libxml2/build.sh b/targets/libxml2/build.sh index 55e463b1f..eefe22578 100755 --- a/targets/libxml2/build.sh +++ b/targets/libxml2/build.sh @@ -28,5 +28,5 @@ cp xmllint "$OUT/" for fuzzer in libxml2_xml_read_memory_fuzzer libxml2_xml_reader_for_file_fuzzer; do $CXX $CXXFLAGS -std=c++11 -Iinclude/ -I"$TARGET/src/" \ "$TARGET/src/$fuzzer.cc" -o "$OUT/$fuzzer" \ - .libs/libxml2.a $LDFLAGS $LIBS -lz -llzma + .libs/libxml2.a $LDFLAGS $LIBS -lz -llzma -include limits done From 4cb95b5685072f6311ce8253f1d8f46bc5f12532 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 09:33:46 +0200 Subject: [PATCH 065/150] Update libfuzzer for Ubuntu 24.04 --- fuzzers/libfuzzer/preinstall.sh | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/fuzzers/libfuzzer/preinstall.sh b/fuzzers/libfuzzer/preinstall.sh index a29feb1e1..420f47cc8 100755 --- a/fuzzers/libfuzzer/preinstall.sh +++ b/fuzzers/libfuzzer/preinstall.sh @@ -4,16 +4,10 @@ set -e LLVM_VERSION=16 apt-get update && \ - apt-get install -y make build-essential wget lsb-release software-properties-common + apt-get install -y make build-essential wget git -add-apt-repository ppa:git-core/ppa -apt-get update && apt-get install -y git - -add-apt-repository -y ppa:ubuntu-toolchain-r/test -wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh -./llvm.sh $LLVM_VERSION - -apt-get install -y libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev +apt-get install -y clang-$LLVM_VERSION \ + libc++-$LLVM_VERSION-dev libc++abi-$LLVM_VERSION-dev update-alternatives \ --install /usr/lib/llvm llvm /usr/lib/llvm-$LLVM_VERSION 20 \ From 626f931ee5202edd30825a9827239f60e9d81e29 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 29 May 2025 16:26:01 +0200 Subject: [PATCH 066/150] Specify start and end years in gen target releases in a nicer way --- gen_target_releases.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gen_target_releases.py b/gen_target_releases.py index be0d74314..bb7bfce0f 100644 --- a/gen_target_releases.py +++ b/gen_target_releases.py @@ -16,6 +16,10 @@ from git import Repo # type: ignore # noqa: E402 +START_YEAR = 2022 +# If START_YEAR=2022, END_YEAR year can be 2025, 2028, 2031, etc. in steps of 3. +END_YEAR = START_YEAR + (((datetime.now().year - START_YEAR) // 3) * 3) + links = { "libpng": "https://github.com/pnggroup/libpng.git", "libsndfile": "https://github.com/libsndfile/libsndfile.git", @@ -60,7 +64,7 @@ def get_tags(repo): # fill the gaps last_tag = 0 - for i in range(min_year, 2025): + for i in range(min_year, END_YEAR): if i in year_to_tag_sorted: last_tag = year_to_tag_sorted[i] else: @@ -92,15 +96,15 @@ def get_first_commit_of_year(repo, year): f'{target}_PIONEER="{link}"\n', f'{target}_PIONEER_STABLE_COMMIT="{stable_hash}"\n', ] - for i in range(2022, 2025): + for i in range(START_YEAR, END_YEAR): releases.append(f'{target}_LEGACY_{i}="{link}"\n') releases.append(f'{target}_LEGACY_{i}_TAG="{year_to_tag[i]}"\n') else: # predefined assert isinstance(link, dict) releases = [ - f'{target}_PIONEER="{link[2024]}"\n', + f'{target}_PIONEER="{link[END_YEAR]}"\n', ] - for i in range(2020, 2025): + for i in range(START_YEAR, END_YEAR): if isinstance(link[i], str): releases.append(f'{target}_LEGACY_{i}="{link[i]}"\n') else: # git repo, + tag or commit From 077e6799dd39c5de6bf00c851a248e25ed43c6b9 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 2 May 2025 18:29:29 +0200 Subject: [PATCH 067/150] Port bugs for libpng --- .../patches/{failed => }/bugs/PNG001.patch | 0 .../patches/{failed => }/bugs/PNG002.patch | 13 +++++------ .../patches/{failed => }/bugs/PNG003.patch | 0 .../patches/{failed => }/bugs/PNG006.patch | 22 +++++++++---------- 4 files changed, 17 insertions(+), 18 deletions(-) rename targets/libpng/patches/{failed => }/bugs/PNG001.patch (100%) rename targets/libpng/patches/{failed => }/bugs/PNG002.patch (79%) rename targets/libpng/patches/{failed => }/bugs/PNG003.patch (100%) rename targets/libpng/patches/{failed => }/bugs/PNG006.patch (58%) diff --git a/targets/libpng/patches/failed/bugs/PNG001.patch b/targets/libpng/patches/bugs/PNG001.patch similarity index 100% rename from targets/libpng/patches/failed/bugs/PNG001.patch rename to targets/libpng/patches/bugs/PNG001.patch diff --git a/targets/libpng/patches/failed/bugs/PNG002.patch b/targets/libpng/patches/bugs/PNG002.patch similarity index 79% rename from targets/libpng/patches/failed/bugs/PNG002.patch rename to targets/libpng/patches/bugs/PNG002.patch index 88e84d169..2ed8f84cc 100644 --- a/targets/libpng/patches/failed/bugs/PNG002.patch +++ b/targets/libpng/patches/bugs/PNG002.patch @@ -46,18 +46,17 @@ index 57b9399..2aba9d7 100644 /* READ APIs * --------- diff --git a/pngerror.c b/pngerror.c -index ec3a709..fed5cdc 100644 +index aa0ae58e1..7671b6cf2 100644 --- a/pngerror.c +++ b/pngerror.c -@@ -951,6 +951,10 @@ png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) - result = function(arg); +@@ -948,6 +948,10 @@ png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg) + return result; } +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (image->flags & PNG_IMAGE_FLAG_INVALID) != 0); ++ MAGMA_LOG("PNG002", (image->flags & PNG_IMAGE_FLAG_INVALID) != 0); +#endif + + /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */ image->opaque->error_buf = saved_error_buf; - - /* And do the cleanup prior to any failure return. */ - + png_image_free(image); diff --git a/targets/libpng/patches/failed/bugs/PNG003.patch b/targets/libpng/patches/bugs/PNG003.patch similarity index 100% rename from targets/libpng/patches/failed/bugs/PNG003.patch rename to targets/libpng/patches/bugs/PNG003.patch diff --git a/targets/libpng/patches/failed/bugs/PNG006.patch b/targets/libpng/patches/bugs/PNG006.patch similarity index 58% rename from targets/libpng/patches/failed/bugs/PNG006.patch rename to targets/libpng/patches/bugs/PNG006.patch index de55580a5..a13520928 100644 --- a/targets/libpng/patches/failed/bugs/PNG006.patch +++ b/targets/libpng/patches/bugs/PNG006.patch @@ -1,3 +1,4 @@ +# Applies cleanly on libpng@ea127968204cc5d10f3fc9250c306b9e8cbd9b80 (libpng16) diff --git a/png.c b/png.c index e92008d..8d3cecb 100644 --- a/png.c @@ -12,18 +13,17 @@ index e92008d..8d3cecb 100644 /* Free any eXIf entry */ if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) { -diff --git a/pngrutil.c b/pngrutil.c -index d5fa08c..2a08277 100644 ---- a/pngrutil.c -+++ b/pngrutil.c -@@ -2059,7 +2059,9 @@ png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) - return; - } +diff --git a/pngset.c b/pngset.c +index 3e63c2724..e73a670a6 100644 +--- a/pngset.c ++++ b/pngset.c +@@ -350,7 +350,9 @@ png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr, + info_ptr->num_exif = num_exif; + info_ptr->exif = new_exif; +#ifdef MAGMA_ENABLE_FIXES info_ptr->free_me |= PNG_FREE_EXIF; +#endif - - info_ptr->eXIf_buf = png_voidcast(png_bytep, - png_malloc_warn(png_ptr, length)); - + info_ptr->valid |= PNG_INFO_eXIf; + } + #endif /* eXIf */ From 293937a350503e28884fb751787a81c8f889be44 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 15:13:48 +0200 Subject: [PATCH 068/150] Port bugs for lua --- .../lua/patches/{failed => }/bugs/LUA001.patch | 12 ++++++------ .../lua/patches/{failed => }/bugs/LUA003.patch | 0 .../lua/patches/{failed => }/bugs/LUA004.patch | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) rename targets/lua/patches/{failed => }/bugs/LUA001.patch (72%) rename targets/lua/patches/{failed => }/bugs/LUA003.patch (100%) rename targets/lua/patches/{failed => }/bugs/LUA004.patch (91%) diff --git a/targets/lua/patches/failed/bugs/LUA001.patch b/targets/lua/patches/bugs/LUA001.patch similarity index 72% rename from targets/lua/patches/failed/bugs/LUA001.patch rename to targets/lua/patches/bugs/LUA001.patch index a6045eef4..01a08f968 100644 --- a/targets/lua/patches/failed/bugs/LUA001.patch +++ b/targets/lua/patches/bugs/LUA001.patch @@ -1,25 +1,25 @@ diff --git a/ldebug.c b/ldebug.c -index 8e3657a9..8b3a61ea 100644 +index 8b4bd546..528a7196 100644 --- a/ldebug.c +++ b/ldebug.c -@@ -181,8 +181,16 @@ static const char *upvalname (const Proto *p, int uv) { +@@ -184,8 +184,16 @@ static const char *upvalname (const Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func))->p->is_vararg) { + if (clLvalue(s2v(ci->func.p))->p->flag & PF_ISVARARG) { int nextra = ci->u.l.nextraargs; +#ifdef MAGMA_ENABLE_FIXES if (n >= -nextra) { /* 'n' is negative */ - *pos = ci->func - nextra - (n + 1); + *pos = ci->func.p - nextra - (n + 1); +#else + if (n <= nextra) { +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", INT_MAX - nextra <= (n - 1)); +#endif -+ *pos = ci->func - nextra + (n - 1); ++ *pos = ci->func.p - nextra + (n - 1); +#endif return "(vararg)"; /* generic name for any vararg */ } } -@@ -195,7 +203,11 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { +@@ -198,7 +206,11 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { const char *name = NULL; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ diff --git a/targets/lua/patches/failed/bugs/LUA003.patch b/targets/lua/patches/bugs/LUA003.patch similarity index 100% rename from targets/lua/patches/failed/bugs/LUA003.patch rename to targets/lua/patches/bugs/LUA003.patch diff --git a/targets/lua/patches/failed/bugs/LUA004.patch b/targets/lua/patches/bugs/LUA004.patch similarity index 91% rename from targets/lua/patches/failed/bugs/LUA004.patch rename to targets/lua/patches/bugs/LUA004.patch index baf5d8848..98f130c6d 100644 --- a/targets/lua/patches/failed/bugs/LUA004.patch +++ b/targets/lua/patches/bugs/LUA004.patch @@ -57,19 +57,19 @@ index 8e3657a9..a4b64532 100644 if (L->status == LUA_YIELD) { /* did hook yield? */ if (counthook) diff --git a/ldo.c b/ldo.c -index 7135079b..2589be9b 100644 +index e9f91384..69edaf3f 100644 --- a/ldo.c +++ b/ldo.c -@@ -368,7 +368,11 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { +@@ -390,7 +390,11 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { int delta = 0; /* correction for vararg functions */ int ftransfer; if (isLua(ci)) { +#ifdef MAGMA_ENABLE_FIXES Proto *p = ci_func(ci)->p; +#else -+ Proto *p = clLvalue(s2v(ci->func))->p; ++ Proto *p = clLvalue(s2v(ci->func.p))->p; +#endif - if (p->is_vararg) + if (p->flag & PF_ISVARARG) delta = ci->u.l.nextraargs + p->numparams + 1; } @@ -377,8 +381,13 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { @@ -101,18 +101,18 @@ index c5e3b437..07524a8e 100644 diff --git a/lstate.h b/lstate.h -index c1283bb6..bc0eadc4 100644 +index 7f567453..8aec3aa0 100644 --- a/lstate.h +++ b/lstate.h -@@ -309,6 +309,9 @@ struct lua_State { - StkId top; /* first free slot in the stack */ +@@ -312,6 +312,9 @@ struct lua_State { + StkIdRel top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ +#ifndef MAGMA_ENABLE_FIXES + const Instruction *oldpc; +#endif - StkId stack_last; /* end of stack (last element + 1) */ - StkId stack; /* stack base */ + StkIdRel stack_last; /* end of stack (last element + 1) */ + StkIdRel stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ @@ -320,7 +323,9 @@ struct lua_State { volatile lua_Hook hook; From 94e5e605bf2770f31d5f26e59f65e35ac1734837 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 16:46:07 +0200 Subject: [PATCH 069/150] Fix placeholder in PNG002 --- targets/libpng/patches/bugs/PNG002.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/libpng/patches/bugs/PNG002.patch b/targets/libpng/patches/bugs/PNG002.patch index 2ed8f84cc..9a3566afb 100644 --- a/targets/libpng/patches/bugs/PNG002.patch +++ b/targets/libpng/patches/bugs/PNG002.patch @@ -54,7 +54,7 @@ index aa0ae58e1..7671b6cf2 100644 } +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("PNG002", (image->flags & PNG_IMAGE_FLAG_INVALID) != 0); ++ MAGMA_LOG("%MAGMA_BUG%", (image->flags & PNG_IMAGE_FLAG_INVALID) != 0); +#endif + /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */ From f66823d38108d25a630c9ae9a83537f6970ef22d Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 17:37:39 +0200 Subject: [PATCH 070/150] Port bugs for openssl renamed: ../../targets/openssl/patches/failed/bugs/SSL008.patch -> ../../targets/openssl/patches/bugs/SSL008.patch renamed: ../../targets/openssl/patches/failed/bugs/SSL015.patch -> ../../targets/openssl/patches/bugs/SSL015.patch new file: ../../targets/openssl/patches/bugs/SSL019.patch renamed: ../../targets/openssl/patches/failed/bugs/SSL020.patch -> ../../targets/openssl/patches/bugs/SSL020.patch deleted: ../../targets/openssl/patches/failed/bugs/SSL019.patch --- .../patches/{failed => }/bugs/SSL008.patch | 2 +- .../patches/{failed => }/bugs/SSL015.patch | 14 +++++------ targets/openssl/patches/bugs/SSL019.patch | 25 +++++++++++++++++++ .../patches/{failed => }/bugs/SSL020.patch | 9 +++---- .../openssl/patches/failed/bugs/SSL019.patch | 25 ------------------- 5 files changed, 36 insertions(+), 39 deletions(-) rename targets/openssl/patches/{failed => }/bugs/SSL008.patch (93%) rename targets/openssl/patches/{failed => }/bugs/SSL015.patch (87%) create mode 100644 targets/openssl/patches/bugs/SSL019.patch rename targets/openssl/patches/{failed => }/bugs/SSL020.patch (64%) delete mode 100644 targets/openssl/patches/failed/bugs/SSL019.patch diff --git a/targets/openssl/patches/failed/bugs/SSL008.patch b/targets/openssl/patches/bugs/SSL008.patch similarity index 93% rename from targets/openssl/patches/failed/bugs/SSL008.patch rename to targets/openssl/patches/bugs/SSL008.patch index 7597c980a..e7c5f1ff3 100644 --- a/targets/openssl/patches/failed/bugs/SSL008.patch +++ b/targets/openssl/patches/bugs/SSL008.patch @@ -22,7 +22,7 @@ ckey = ssl_generate_pkey(s, skey); +#ifdef MAGMA_ENABLE_FIXES if (ckey == NULL) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE); + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_SSL_LIB); goto err; } +#endif diff --git a/targets/openssl/patches/failed/bugs/SSL015.patch b/targets/openssl/patches/bugs/SSL015.patch similarity index 87% rename from targets/openssl/patches/failed/bugs/SSL015.patch rename to targets/openssl/patches/bugs/SSL015.patch index 50d3487bf..7712b6f58 100644 --- a/targets/openssl/patches/failed/bugs/SSL015.patch +++ b/targets/openssl/patches/bugs/SSL015.patch @@ -64,25 +64,23 @@ index 2cf62b62cd..f53a5e0082 100644 ctx_tmp = EVP_MD_CTX_new(); if (ctx_tmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); -@@ -920,7 +960,8 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, - int ret = 0, i; - STACK_OF(X509) *cert; - X509 *x509; +@@ -1007,6 +1007,7 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, + STACK_OF(X509_CRL) *crls; + X509 *signer; +#ifdef MAGMA_ENABLE_FIXES if (p7 == NULL) { ERR_raise(ERR_LIB_PKCS7, PKCS7_R_INVALID_NULL_POINTER); return 0; -@@ -930,7 +970,12 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, +@@ -1016,6 +1017,11 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT); return 0; } - +#else +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(p7 == NULL, p7->d.ptr)); +#endif +#endif + if (PKCS7_type_is_signed(p7)) { - cert = p7->d.sign->cert; - } else if (PKCS7_type_is_signedAndEnveloped(p7)) { + untrusted = p7->d.sign->cert; diff --git a/targets/openssl/patches/bugs/SSL019.patch b/targets/openssl/patches/bugs/SSL019.patch new file mode 100644 index 000000000..a062d1ad7 --- /dev/null +++ b/targets/openssl/patches/bugs/SSL019.patch @@ -0,0 +1,25 @@ +diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c +index 0930222edb..22c9e52f46 100644 +--- a/ssl/record/rec_layer_s3.c ++++ b/ssl/record/rec_layer_s3.c +@@ -791,11 +791,20 @@ int ssl3_read_bytes(SSL *ssl, uint8_t type, uint8_t *recvd_type, + + memcpy(buf, &(rr->data[rr->off]), n); + buf += n; ++#ifdef MAGMA_ENABLE_FIXES + if (peek) { + /* Mark any zero length record as consumed CVE-2016-6305 */ + if (rr->length == 0 && !ssl_release_record(s, rr, 0)) + return -1; + } else { ++#else ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(peek, \ ++ MAGMA_AND(rr->length == 0, \ ++ !ssl_release_record(s, rr, 0)))); ++#endif ++ if (!peek) { ++#endif + if (!ssl_release_record(s, rr, n)) + return -1; + } diff --git a/targets/openssl/patches/failed/bugs/SSL020.patch b/targets/openssl/patches/bugs/SSL020.patch similarity index 64% rename from targets/openssl/patches/failed/bugs/SSL020.patch rename to targets/openssl/patches/bugs/SSL020.patch index 3c45d793f..c09850a84 100644 --- a/targets/openssl/patches/failed/bugs/SSL020.patch +++ b/targets/openssl/patches/bugs/SSL020.patch @@ -1,14 +1,13 @@ diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c -index 923cf5b5cd..6ed2362391 100644 +index 5a7201b7a2..56f9bdbf8b 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c -@@ -1550,11 +1556,18 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick, +@@ -3184,10 +3184,17 @@ SSL_TICKET_STATUS tls_decrypt_ticket(SSL_CONNECTION *s, } /* Sanity check ticket length: must exceed keyname + IV + HMAC */ +#ifdef MAGMA_ENABLE_FIXES - if (eticklen <= - TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_get_iv_length(ctx) + mlen) { + if (eticklen <= TLSEXT_KEYNAME_LENGTH + ivlen + mlen) { +#else + if (eticklen < 48) { +#endif @@ -16,7 +15,7 @@ index 923cf5b5cd..6ed2362391 100644 goto end; } +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", eticklen <= TLSEXT_KEYNAME_LENGTH + EVP_CIPHER_CTX_get_iv_length(ctx) + mlen); ++ MAGMA_LOG("%MAGMA_BUG%", eticklen <= TLSEXT_KEYNAME_LENGTH + ivlen + mlen); +#endif eticklen -= mlen; /* Check HMAC of encrypted ticket */ diff --git a/targets/openssl/patches/failed/bugs/SSL019.patch b/targets/openssl/patches/failed/bugs/SSL019.patch deleted file mode 100644 index e141bc46e..000000000 --- a/targets/openssl/patches/failed/bugs/SSL019.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c -index b4675f3c8c..cfd1b5d415 100644 ---- a/ssl/record/rec_layer_s3.c -+++ b/ssl/record/rec_layer_s3.c -@@ -1469,11 +1469,20 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf, - - memcpy(buf, &(rr->data[rr->off]), n); - buf += n; -+#ifdef MAGMA_ENABLE_FIXES - if (peek) { - /* Mark any zero length record as consumed CVE-2016-6305 */ - if (SSL3_RECORD_get_length(rr) == 0) - SSL3_RECORD_set_read(rr); - } else { -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(peek, \ -+ MAGMA_AND(SSL3_RECORD_get_length(rr) == 0, \ -+ !SSL3_RECORD_is_read(rr)))); -+#endif -+ if (!peek) { -+#endif - if (s->options & SSL_OP_CLEANSE_PLAINTEXT) - OPENSSL_cleanse(&(rr->data[rr->off]), n); - SSL3_RECORD_sub_length(rr, n); From df34e16a7416991d203a7c17c766209768f02497 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 3 May 2025 20:26:02 +0200 Subject: [PATCH 071/150] Port bugs for poppler --- .../patches/{failed => }/bugs/PDF002.patch | 9 +- .../patches/{failed => }/bugs/PDF003.patch | 6 +- .../patches/{failed => }/bugs/PDF004.patch | 7 +- .../patches/{failed => }/bugs/PDF006.patch | 14 +-- .../patches/{failed => }/bugs/PDF007.patch | 10 +- .../patches/{failed => }/bugs/PDF009.patch | 7 +- .../patches/{failed => }/bugs/PDF015.patch | 12 +- .../patches/{failed => }/bugs/PDF017.patch | 15 ++- .../patches/{failed => }/bugs/PDF018.patch | 8 +- .../patches/{failed => }/bugs/PDF019.patch | 11 +- targets/poppler/patches/bugs/PDF022.patch | 29 +++++ .../poppler/patches/failed/bugs/PDF022.patch | 108 ------------------ 12 files changed, 81 insertions(+), 155 deletions(-) rename targets/poppler/patches/{failed => }/bugs/PDF002.patch (78%) rename targets/poppler/patches/{failed => }/bugs/PDF003.patch (94%) rename targets/poppler/patches/{failed => }/bugs/PDF004.patch (78%) rename targets/poppler/patches/{failed => }/bugs/PDF006.patch (66%) rename targets/poppler/patches/{failed => }/bugs/PDF007.patch (69%) rename targets/poppler/patches/{failed => }/bugs/PDF009.patch (71%) rename targets/poppler/patches/{failed => }/bugs/PDF015.patch (65%) rename targets/poppler/patches/{failed => }/bugs/PDF017.patch (64%) rename targets/poppler/patches/{failed => }/bugs/PDF018.patch (71%) rename targets/poppler/patches/{failed => }/bugs/PDF019.patch (62%) create mode 100644 targets/poppler/patches/bugs/PDF022.patch delete mode 100644 targets/poppler/patches/failed/bugs/PDF022.patch diff --git a/targets/poppler/patches/failed/bugs/PDF002.patch b/targets/poppler/patches/bugs/PDF002.patch similarity index 78% rename from targets/poppler/patches/failed/bugs/PDF002.patch rename to targets/poppler/patches/bugs/PDF002.patch index ecccd0e47..0cb2b68db 100644 --- a/targets/poppler/patches/failed/bugs/PDF002.patch +++ b/targets/poppler/patches/bugs/PDF002.patch @@ -1,20 +1,21 @@ diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc -index 8e6902f..0fe7a62 100644 +index 67d28a8c..a678d3d8 100644 --- a/poppler/JPEG2000Stream.cc +++ b/poppler/JPEG2000Stream.cc -@@ -219,8 +219,15 @@ void JPXStream::init() +@@ -242,9 +242,16 @@ void JPXStream::init() } int bufSize = BUFFER_INITIAL_SIZE; +#ifdef MAGMA_ENABLE_FIXES - if (oLen.isInt() && oLen.getInt() > 0) + if (oLen.isInt() && oLen.getInt() > 0) { bufSize = oLen.getInt(); + } +#else +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", oLen.getInt() < 0); +#endif + if (oLen.isInt()) bufSize = oLen.getInt(); +#endif - + bool indexed = false; if (cspace.isArray() && cspace.arrayGetLength() > 0) { diff --git a/targets/poppler/patches/failed/bugs/PDF003.patch b/targets/poppler/patches/bugs/PDF003.patch similarity index 94% rename from targets/poppler/patches/failed/bugs/PDF003.patch rename to targets/poppler/patches/bugs/PDF003.patch index e7558d44c..387697ec2 100644 --- a/targets/poppler/patches/failed/bugs/PDF003.patch +++ b/targets/poppler/patches/bugs/PDF003.patch @@ -45,13 +45,13 @@ index 850eb10..7a89884 100644 if (colToByte(gray) == 0) invert_bits = 0x00; diff --git a/poppler/GfxState.h b/poppler/GfxState.h -index 7a6e4031..caa5c164 100644 +index 6e988fd3..ae25e3fd 100644 --- a/poppler/GfxState.h +++ b/poppler/GfxState.h -@@ -1192,6 +1192,7 @@ public: +@@ -1242,6 +1242,7 @@ public: // Get the color space. - GfxColorSpace *getColorSpace() { return colorSpace; } + GfxColorSpace *getColorSpace() { return colorSpace.get(); } + GfxColorSpace *getColorSpace2() { return colorSpace2; } // Get stream decoding info. diff --git a/targets/poppler/patches/failed/bugs/PDF004.patch b/targets/poppler/patches/bugs/PDF004.patch similarity index 78% rename from targets/poppler/patches/failed/bugs/PDF004.patch rename to targets/poppler/patches/bugs/PDF004.patch index 267e15b4c..3e76d2db1 100644 --- a/targets/poppler/patches/failed/bugs/PDF004.patch +++ b/targets/poppler/patches/bugs/PDF004.patch @@ -1,14 +1,15 @@ diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc -index 042a6ef..d1ab6b1 100644 +index 3d7db3ac..e7390903 100644 --- a/splash/SplashXPathScanner.cc +++ b/splash/SplashXPathScanner.cc -@@ -455,8 +455,13 @@ void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf, +@@ -449,9 +449,14 @@ void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf, const int *x0, const in xx = *x0 * splashAASize; if (yy >= yyMin && yy <= yyMax) { const int intersectionIndex = splashAASize * y + yy - yMin; +#ifdef MAGMA_ENABLE_FIXES - if (unlikely(intersectionIndex < 0 || (unsigned)intersectionIndex >= allIntersections.size())) + if (unlikely(intersectionIndex < 0 || (unsigned)intersectionIndex >= allIntersections.size())) { break; + } +#endif +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(intersectionIndex < 0, (unsigned)intersectionIndex >= allIntersections.size())); diff --git a/targets/poppler/patches/failed/bugs/PDF006.patch b/targets/poppler/patches/bugs/PDF006.patch similarity index 66% rename from targets/poppler/patches/failed/bugs/PDF006.patch rename to targets/poppler/patches/bugs/PDF006.patch index 1c2b72939..cb80cd0fd 100644 --- a/targets/poppler/patches/failed/bugs/PDF006.patch +++ b/targets/poppler/patches/bugs/PDF006.patch @@ -1,19 +1,19 @@ diff --git a/splash/Splash.cc b/splash/Splash.cc -index 654608c..2405541 100644 +index 3d2576a7..d7119801 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc -@@ -5862,6 +5862,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, +@@ -5871,6 +5871,7 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, int x return splashErrZeroImage; } +#ifdef MAGMA_ENABLE_FIXES - if (src->getWidth() - xSrc < width) + if (src->getWidth() - xSrc < width) { width = src->getWidth() - xSrc; - -@@ -5879,6 +5880,15 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - - if (height < 0) + } +@@ -5894,6 +5895,15 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, int x + if (height < 0) { height = 0; + } +#else +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(src->getWidth() - xSrc < width, \ diff --git a/targets/poppler/patches/failed/bugs/PDF007.patch b/targets/poppler/patches/bugs/PDF007.patch similarity index 69% rename from targets/poppler/patches/failed/bugs/PDF007.patch rename to targets/poppler/patches/bugs/PDF007.patch index f90b9fbd7..62f25fe8c 100644 --- a/targets/poppler/patches/failed/bugs/PDF007.patch +++ b/targets/poppler/patches/bugs/PDF007.patch @@ -1,10 +1,10 @@ diff --git a/poppler/Stream.cc b/poppler/Stream.cc -index 99ccbd2..581dcd5 100644 +index 8aee314d..515872f1 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc -@@ -496,9 +496,14 @@ unsigned char *ImageStream::getLine() { +@@ -667,9 +667,14 @@ unsigned char *ImageStream::getLine() } - + int readChars = str->doGetChars(inputLineSize, inputLine); +#ifdef MAGMA_ENABLE_FIXES if (unlikely(readChars == -1)) { @@ -14,6 +14,6 @@ index 99ccbd2..581dcd5 100644 +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", readChars < 0); +#endif - for (; readChars < inputLineSize; readChars++) + for (; readChars < inputLineSize; readChars++) { inputLine[readChars] = EOF; - if (nBits == 1) { + } diff --git a/targets/poppler/patches/failed/bugs/PDF009.patch b/targets/poppler/patches/bugs/PDF009.patch similarity index 71% rename from targets/poppler/patches/failed/bugs/PDF009.patch rename to targets/poppler/patches/bugs/PDF009.patch index b7805b969..542c5a260 100644 --- a/targets/poppler/patches/failed/bugs/PDF009.patch +++ b/targets/poppler/patches/bugs/PDF009.patch @@ -1,14 +1,15 @@ diff --git a/poppler/Parser.cc b/poppler/Parser.cc -index 0cb1f7f..d273504 100644 +index ce0f1fd2..c808a031 100644 --- a/poppler/Parser.cc +++ b/poppler/Parser.cc -@@ -283,8 +283,15 @@ Stream *Parser::makeStream(Object &&dict, unsigned char *fileKey, +@@ -307,9 +307,16 @@ Stream *Parser::makeStream(Object &&dict, const unsigned char *fileKey, CryptAlg // When building the xref we can't use it so use this // kludge for broken PDF files: just add 5k to the length, and // hope its enough +#ifdef MAGMA_ENABLE_FIXES - if (length < LLONG_MAX - pos - 5000) + if (length < LLONG_MAX - pos - 5000) { length += 5000; + } +#else +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", length >= LLONG_MAX - pos - 5000); diff --git a/targets/poppler/patches/failed/bugs/PDF015.patch b/targets/poppler/patches/bugs/PDF015.patch similarity index 65% rename from targets/poppler/patches/failed/bugs/PDF015.patch rename to targets/poppler/patches/bugs/PDF015.patch index 46263a300..6da5cf29e 100644 --- a/targets/poppler/patches/failed/bugs/PDF015.patch +++ b/targets/poppler/patches/bugs/PDF015.patch @@ -1,19 +1,19 @@ diff --git a/poppler/FileSpec.cc b/poppler/FileSpec.cc -index be262ad4..445931f3 100644 +index 62782603..985483f8 100644 --- a/poppler/FileSpec.cc +++ b/poppler/FileSpec.cc -@@ -97,9 +97,13 @@ bool EmbFile::save(const char *path) { - bool EmbFile::save2(FILE *f) { +@@ -104,9 +104,14 @@ bool EmbFile::save2(FILE *f) + { int c; +#ifdef MAGMA_ENABLE_FIXES - if (unlikely(!m_objStr.isStream())) + if (unlikely(!m_objStr.isStream())) { return false; -- + } +#endif +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", !m_objStr.isStream()); +#endif + m_objStr.streamReset(); while ((c = m_objStr.streamGetChar()) != EOF) { - fputc(c, f); diff --git a/targets/poppler/patches/failed/bugs/PDF017.patch b/targets/poppler/patches/bugs/PDF017.patch similarity index 64% rename from targets/poppler/patches/failed/bugs/PDF017.patch rename to targets/poppler/patches/bugs/PDF017.patch index 5f0d3be9a..730dd42c2 100644 --- a/targets/poppler/patches/failed/bugs/PDF017.patch +++ b/targets/poppler/patches/bugs/PDF017.patch @@ -1,10 +1,10 @@ diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc -index 24624352..6a48384b 100644 +index c6cb8233..59647e4a 100644 --- a/fofi/FoFiTrueType.cc +++ b/fofi/FoFiTrueType.cc -@@ -1227,16 +1227,28 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, +@@ -1373,15 +1373,27 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const if ((j = seekTable(t42Tables[i].tag)) >= 0 && checkRegion(tables[j].offset, tables[j].len)) { - dumpString(file + tables[j].offset, tables[j].len, outputFunc, outputStream); + dumpString(std::span(file + tables[j].offset, tables[j].len), outputFunc, outputStream); } else if (needVerticalMetrics && i == t42VheaTable) { +#ifdef MAGMA_ENABLE_FIXES if (unlikely(length > (int)sizeof(vheaTab))) { @@ -16,18 +16,17 @@ index 24624352..6a48384b 100644 + MAGMA_LOG("%MAGMA_BUG%", length > (int)sizeof(vheaTab)); +#endif +#endif - dumpString(vheaTab, length, outputFunc, outputStream); + dumpString(vheaTab, outputFunc, outputStream); } else if (needVerticalMetrics && i == t42VmtxTable) { +#ifdef MAGMA_ENABLE_FIXES - if (unlikely(length > vmtxTabLength)) { + if (unlikely(length > (int)vmtxTab.size())) { error(errSyntaxWarning, -1, "length bigger than vmtxTab size"); - length = vmtxTabLength; } +#else +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", length > vmtxTabLength); ++ MAGMA_LOG("%MAGMA_BUG%", length > (int)vmtxTab.size()); +#endif +#endif - dumpString(vmtxTab, length, outputFunc, outputStream); + dumpString(vmtxTab, outputFunc, outputStream); } } diff --git a/targets/poppler/patches/failed/bugs/PDF018.patch b/targets/poppler/patches/bugs/PDF018.patch similarity index 71% rename from targets/poppler/patches/failed/bugs/PDF018.patch rename to targets/poppler/patches/bugs/PDF018.patch index de19cbff3..d57707732 100644 --- a/targets/poppler/patches/failed/bugs/PDF018.patch +++ b/targets/poppler/patches/bugs/PDF018.patch @@ -1,11 +1,11 @@ diff --git a/poppler/Annot.cc b/poppler/Annot.cc -index 37165e38..095a9d09 100644 +index 0b2733b9..22df46a9 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc -@@ -5897,7 +5897,14 @@ void AnnotInk::draw(Gfx *gfx, bool printing) { +@@ -6624,7 +6624,14 @@ void AnnotInk::draw(Gfx *gfx, bool printing) + appearBBox->setBorderWidth(std::max(1., border->getWidth())); - for (int i = 0; i < inkListLength; ++i) { - const AnnotPath *path = inkList[i]; + for (const auto &path : inkList) { +#ifdef MAGMA_ENABLE_FIXES if (path && path->getCoordsLength() != 0) { +#else diff --git a/targets/poppler/patches/failed/bugs/PDF019.patch b/targets/poppler/patches/bugs/PDF019.patch similarity index 62% rename from targets/poppler/patches/failed/bugs/PDF019.patch rename to targets/poppler/patches/bugs/PDF019.patch index 35af5de31..e224087b4 100644 --- a/targets/poppler/patches/failed/bugs/PDF019.patch +++ b/targets/poppler/patches/bugs/PDF019.patch @@ -1,14 +1,18 @@ diff --git a/poppler/JBIG2Stream.cc b/poppler/JBIG2Stream.cc -index a861da21..fd38c198 100644 +index 0dffc111..35872893 100644 --- a/poppler/JBIG2Stream.cc +++ b/poppler/JBIG2Stream.cc -@@ -902,9 +902,14 @@ void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, +@@ -809,12 +809,17 @@ void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, unsigned int combOp oneByte = x0 == ((x1 - 1) & ~7); for (yy = y0; yy < y1; ++yy) { +#ifdef MAGMA_ENABLE_FIXES - if (unlikely((y + yy >= h) || (y + yy < 0))) + if (unlikely(checkedAdd(y, yy, &yyy))) { continue; + } + if (unlikely((yyy >= h) || (yyy < 0))) { + continue; + } +#endif +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(y + yy >= h, y + yy < 0)); @@ -16,4 +20,3 @@ index a861da21..fd38c198 100644 // one byte per line -- need to mask both left and right side if (oneByte) { - if (x >= 0) { diff --git a/targets/poppler/patches/bugs/PDF022.patch b/targets/poppler/patches/bugs/PDF022.patch new file mode 100644 index 000000000..c7ddec588 --- /dev/null +++ b/targets/poppler/patches/bugs/PDF022.patch @@ -0,0 +1,29 @@ +diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc +index aa7b592d..7c863bb5 100644 +--- a/poppler/GfxState.cc ++++ b/poppler/GfxState.cc +@@ -2665,16 +2665,24 @@ void GfxSeparationColorSpace::getGray(const GfxColor *color, GfxGray *gray) cons + GfxColor color2; + int i; + ++#ifdef MAGMA_ENABLE_FIXES + if (alt->getMode() == csDeviceGray && name->cmp("Black") == 0) { + *gray = clip01(gfxColorComp1 - color->c[0]); + } else { ++#else ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(alt->getMode() == csDeviceGray, name->cmp("Black") == 0)); ++#endif ++#endif + x = colToDbl(color->c[0]); + func->transform(&x, c); + for (i = 0; i < alt->getNComps(); ++i) { + color2.c[i] = dblToCol(c[i]); + } + alt->getGray(&color2, gray); ++#ifdef MAGMA_ENABLE_FIXES + } ++#endif + } + + void GfxSeparationColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const diff --git a/targets/poppler/patches/failed/bugs/PDF022.patch b/targets/poppler/patches/failed/bugs/PDF022.patch deleted file mode 100644 index 8de7648b3..000000000 --- a/targets/poppler/patches/failed/bugs/PDF022.patch +++ /dev/null @@ -1,108 +0,0 @@ -diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc -index 9aca67b3..8d5e89f2 100644 ---- a/poppler/GfxState.cc -+++ b/poppler/GfxState.cc -@@ -2701,16 +2701,24 @@ void GfxSeparationColorSpace::getGray(const GfxColor *color, GfxGray *gray) cons - GfxColor color2; - int i; - -+#ifdef MAGMA_ENABLE_FIXES - if (alt->getMode() == csDeviceGray && name->cmp("Black") == 0) { - *gray = clip01(gfxColorComp1 - color->c[0]); - } else { -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(alt->getMode() == csDeviceGray, name->cmp("Black") == 0)); -+#endif -+#endif - x = colToDbl(color->c[0]); - func->transform(&x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getGray(&color2, gray); -+#ifdef MAGMA_ENABLE_FIXES - } -+#endif - } - - void GfxSeparationColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const { -@@ -2719,24 +2727,32 @@ void GfxSeparationColorSpace::getRGB(const GfxColor *color, GfxRGB *rgb) const { - GfxColor color2; - int i; - -+#ifdef MAGMA_ENABLE_FIXES - if (alt->getMode() == csDeviceGray && name->cmp("Black") == 0) { - rgb->r = clip01(gfxColorComp1 - color->c[0]); - rgb->g = clip01(gfxColorComp1 - color->c[0]); - rgb->b = clip01(gfxColorComp1 - color->c[0]); - } else { -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(alt->getMode() == csDeviceGray, name->cmp("Black") == 0)); -+#endif -+#endif - x = colToDbl(color->c[0]); - func->transform(&x, c); - const int altNComps = alt->getNComps(); - for (i = 0; i < altNComps; ++i) { - color2.c[i] = dblToCol(c[i]); - } - if (unlikely(altNComps > func->getOutputSize())) { - for (i = func->getOutputSize(); i < altNComps; ++i) { - color2.c[i] = 0; - } - } - alt->getRGB(&color2, rgb); -+#ifdef MAGMA_ENABLE_FIXES - } -+#endif - } - - void GfxSeparationColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) const { -@@ -2745,34 +2761,45 @@ void GfxSeparationColorSpace::getCMYK(const GfxColor *color, GfxCMYK *cmyk) cons - GfxColor color2; - int i; - -+#ifdef MAGMA_ENABLE_FIXES - if (name->cmp("Black") == 0) { - cmyk->c = 0; - cmyk->m = 0; - cmyk->y = 0; - cmyk->k = color->c[0]; - } else if (name->cmp("Cyan") == 0) { - cmyk->c = color->c[0]; - cmyk->m = 0; - cmyk->y = 0; - cmyk->k = 0; - } else if (name->cmp("Magenta") == 0) { - cmyk->c = 0; - cmyk->m = color->c[0]; - cmyk->y = 0; - cmyk->k = 0; - } else if (name->cmp("Yellow") == 0) { - cmyk->c = 0; - cmyk->m = 0; - cmyk->y = color->c[0]; - cmyk->k = 0; - } else { -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(name->cmp("Black") == 0, \ -+ MAGMA_OR(name->cmp("Cyan") == 0, \ -+ MAGMA_OR(name->cmp("Magenta") == 0, \ -+ name->cmp("Yellow") == 0)))); -+#endif -+#endif - x = colToDbl(color->c[0]); - func->transform(&x, c); - for (i = 0; i < alt->getNComps(); ++i) { - color2.c[i] = dblToCol(c[i]); - } - alt->getCMYK(&color2, cmyk); -+#ifdef MAGMA_ENABLE_FIXES - } -+#endif - } - - void GfxSeparationColorSpace::getDeviceN(const GfxColor *color, GfxColor *deviceN) const { From 95a945d2d7df52c9ea634e18e4f11be08a224717 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sun, 4 May 2025 19:45:07 +0200 Subject: [PATCH 072/150] Port bugs for sqlite3 --- .../patches/{failed => }/bugs/SQL001.patch | 8 ++- .../patches/{failed => }/bugs/SQL002.patch | 15 +++-- targets/sqlite3/patches/bugs/SQL003.patch | 21 +++++++ .../patches/{failed => }/bugs/SQL006.patch | 15 ++--- .../patches/{failed => }/bugs/SQL007.patch | 6 +- .../patches/{failed => }/bugs/SQL014.patch | 8 +-- .../patches/{failed => }/bugs/SQL015.patch | 11 ++-- targets/sqlite3/patches/bugs/SQL017.patch | 57 +++++++++++++++++++ .../sqlite3/patches/failed/bugs/SQL003.patch | 20 ------- .../sqlite3/patches/failed/bugs/SQL012.patch | 22 ------- .../sqlite3/patches/failed/bugs/SQL017.patch | 55 ------------------ .../sqlite3/patches/graveyard/SQL012.patch | 42 ++++++++++++++ .../{failed/bugs => graveyard}/SQL019.patch | 12 ++++ 13 files changed, 167 insertions(+), 125 deletions(-) rename targets/sqlite3/patches/{failed => }/bugs/SQL001.patch (69%) rename targets/sqlite3/patches/{failed => }/bugs/SQL002.patch (59%) create mode 100644 targets/sqlite3/patches/bugs/SQL003.patch rename targets/sqlite3/patches/{failed => }/bugs/SQL006.patch (59%) rename targets/sqlite3/patches/{failed => }/bugs/SQL007.patch (73%) rename targets/sqlite3/patches/{failed => }/bugs/SQL014.patch (75%) rename targets/sqlite3/patches/{failed => }/bugs/SQL015.patch (78%) create mode 100644 targets/sqlite3/patches/bugs/SQL017.patch delete mode 100644 targets/sqlite3/patches/failed/bugs/SQL003.patch delete mode 100644 targets/sqlite3/patches/failed/bugs/SQL012.patch delete mode 100644 targets/sqlite3/patches/failed/bugs/SQL017.patch create mode 100644 targets/sqlite3/patches/graveyard/SQL012.patch rename targets/sqlite3/patches/{failed/bugs => graveyard}/SQL019.patch (56%) diff --git a/targets/sqlite3/patches/failed/bugs/SQL001.patch b/targets/sqlite3/patches/bugs/SQL001.patch similarity index 69% rename from targets/sqlite3/patches/failed/bugs/SQL001.patch rename to targets/sqlite3/patches/bugs/SQL001.patch index 0390a2af4..8f4a39b9f 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL001.patch +++ b/targets/sqlite3/patches/bugs/SQL001.patch @@ -1,16 +1,18 @@ +diff --git a/ext/fts5/fts5_hash.c b/ext/fts5/fts5_hash.c +index 5e0959aa8e..b0c59321ce 100644 --- a/ext/fts5/fts5_hash.c +++ b/ext/fts5/fts5_hash.c -@@ -456,9 +456,16 @@ static int fts5HashEntrySort( +@@ -463,9 +463,16 @@ static int fts5HashEntrySort( for(iSlot=0; iSlotnSlot; iSlot++){ Fts5HashEntry *pIter; for(pIter=pHash->aSlot[iSlot]; pIter; pIter=pIter->pHashNext){ +#ifdef MAGMA_ENABLE_FIXES if( pTerm==0 - || (pIter->nKey+1>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) + || (pIter->nKey>=nTerm && 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) ){ +#else +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(pTerm != 0, pIter->nKey+1 < nTerm)); ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(pTerm != 0, pIter->nKey < nTerm)); +#endif + if(pTerm==0 || 0==memcmp(fts5EntryKey(pIter), pTerm, nTerm)) { +#endif diff --git a/targets/sqlite3/patches/failed/bugs/SQL002.patch b/targets/sqlite3/patches/bugs/SQL002.patch similarity index 59% rename from targets/sqlite3/patches/failed/bugs/SQL002.patch rename to targets/sqlite3/patches/bugs/SQL002.patch index b51ec4a1c..74bf1834a 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL002.patch +++ b/targets/sqlite3/patches/bugs/SQL002.patch @@ -1,20 +1,23 @@ diff --git a/src/select.c b/src/select.c -index a9ec1e852..0ce67e935 100644 +index cf25c8e678..53cc27c4cc 100644 --- a/src/select.c +++ b/src/select.c -@@ -5008,9 +5008,16 @@ static int selectExpander(Walker *pWalker, Select *p){ +@@ -6140,10 +6140,17 @@ static int selectExpander(Walker *pWalker, Select *p){ /* Process NATURAL keywords, and ON and USING clauses of joins. */ -- if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){ +- assert( db->mallocFailed==0 || pParse->nErr!=0 ); +- if( pParse->nErr || sqlite3ProcessJoin(pParse, p) ){ - return WRC_Abort; +- } ++ + if( +#ifdef MAGMA_ENABLE_FIXES -+ pParse->nErr || ++ pParse->nErr || +#endif -+ db->mallocFailed || sqliteProcessJoin(pParse, p) ){ ++ db->mallocFailed || sqlite3ProcessJoin(pParse, p) ){ + return WRC_Abort; - } ++ } +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", pParse->nErr); +#endif diff --git a/targets/sqlite3/patches/bugs/SQL003.patch b/targets/sqlite3/patches/bugs/SQL003.patch new file mode 100644 index 000000000..de3b23de7 --- /dev/null +++ b/targets/sqlite3/patches/bugs/SQL003.patch @@ -0,0 +1,21 @@ +diff --git a/src/select.c b/src/select.c +index cf25c8e678..be9913db44 100644 +--- a/src/select.c ++++ b/src/select.c +@@ -4431,11 +4431,16 @@ static int flattenSubquery( + if( (pSubitem->fg.jointype & (JT_OUTER|JT_LTORJ))!=0 ){ + if( pSubSrc->nSrc>1 /* (3a) */ + || IsVirtual(pSubSrc->a[0].pSTab) /* (3b) */ ++#ifdef MAGMA_ENABLE_FIXES + || (p->selFlags & SF_Distinct)!=0 /* (3d) */ ++#endif + || (pSubitem->fg.jointype & JT_RIGHT)!=0 /* (26) */ + ){ + return 0; + } ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (p->selFlags & SF_Distinct)!=0); ++#endif + isOuterJoin = 1; + } + diff --git a/targets/sqlite3/patches/failed/bugs/SQL006.patch b/targets/sqlite3/patches/bugs/SQL006.patch similarity index 59% rename from targets/sqlite3/patches/failed/bugs/SQL006.patch rename to targets/sqlite3/patches/bugs/SQL006.patch index cfdd52943..b5e62c3ae 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL006.patch +++ b/targets/sqlite3/patches/bugs/SQL006.patch @@ -1,16 +1,17 @@ diff --git a/src/select.c b/src/select.c -index a9ec1e852..8c8c9d0bf 100644 +index cf25c8e678..9521977683 100644 --- a/src/select.c +++ b/src/select.c -@@ -6123,10 +6123,17 @@ int sqlite3Select( - */ - if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct +@@ -7975,10 +7975,17 @@ int sqlite3Select( + if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 + && OptimizationEnabled(db, SQLITE_GroupByOrder) +-#ifndef SQLITE_OMIT_WINDOWFUNC +#ifdef MAGMA_ENABLE_FIXES - #ifndef SQLITE_OMIT_WINDOWFUNC ++ #ifndef SQLITE_OMIT_WINDOWFUNC && p->pWin==0 ++ #endif #endif -+#endif ){ +#ifdef MAGMA_ENABLE_CANARIES +#ifndef SQLITE_OMIT_WINDOWFUNC @@ -19,4 +20,4 @@ index a9ec1e852..8c8c9d0bf 100644 +#endif p->selFlags &= ~SF_Distinct; pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); - p->selFlags |= SF_Aggregate; + if( pGroupBy ){ diff --git a/targets/sqlite3/patches/failed/bugs/SQL007.patch b/targets/sqlite3/patches/bugs/SQL007.patch similarity index 73% rename from targets/sqlite3/patches/failed/bugs/SQL007.patch rename to targets/sqlite3/patches/bugs/SQL007.patch index d87a574e0..944262e48 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL007.patch +++ b/targets/sqlite3/patches/bugs/SQL007.patch @@ -1,13 +1,13 @@ diff --git a/src/build.c b/src/build.c -index 73e4cea7c..593b31617 100644 +index a5deb54fc6..8d9de5bc72 100644 --- a/src/build.c +++ b/src/build.c -@@ -2236,10 +2236,15 @@ void sqlite3EndTable( +@@ -2626,10 +2626,15 @@ void sqlite3EndTable( ** table itself. So mark it read-only. */ if( db->init.busy ){ +#ifdef MAGMA_ENABLE_FIXES - if( pSelect ){ + if( pSelect || (!IsOrdinaryTable(p) && db->init.newTnum) ){ sqlite3ErrorMsg(pParse, ""); return; } diff --git a/targets/sqlite3/patches/failed/bugs/SQL014.patch b/targets/sqlite3/patches/bugs/SQL014.patch similarity index 75% rename from targets/sqlite3/patches/failed/bugs/SQL014.patch rename to targets/sqlite3/patches/bugs/SQL014.patch index 722fce9cd..980cf066d 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL014.patch +++ b/targets/sqlite3/patches/bugs/SQL014.patch @@ -1,18 +1,18 @@ diff --git a/src/select.c b/src/select.c -index b2dd5f149..61c4cb9f9 100644 +index cf25c8e678..4fcb84841c 100644 --- a/src/select.c +++ b/src/select.c -@@ -2833,8 +2833,12 @@ static int multiSelect( +@@ -3170,8 +3170,12 @@ static int multiSelect( } #endif } +#ifdef MAGMA_ENABLE_FIXES if( pParse->nErr ) goto multi_select_end; -- +- +#endif +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", pParse->nErr != 0); +#endif - /* Compute collating sequences used by + /* Compute collating sequences used by ** temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. diff --git a/targets/sqlite3/patches/failed/bugs/SQL015.patch b/targets/sqlite3/patches/bugs/SQL015.patch similarity index 78% rename from targets/sqlite3/patches/failed/bugs/SQL015.patch rename to targets/sqlite3/patches/bugs/SQL015.patch index 081253068..3a590a0ba 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL015.patch +++ b/targets/sqlite3/patches/bugs/SQL015.patch @@ -1,19 +1,21 @@ diff --git a/src/resolve.c b/src/resolve.c -index e90e8a768..654bf133e 100644 +index d6a5144af8..eb37ee893c 100644 --- a/src/resolve.c +++ b/src/resolve.c -@@ -182,22 +182,37 @@ static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){ +@@ -179,24 +179,38 @@ static int areDoubleQuotedStringsEnabled(sqlite3 *db, NameContext *pTopNC){ Bitmask sqlite3ExprColUsed(Expr *pExpr){ int n; Table *pExTab; + Bitmask result; n = pExpr->iColumn; + assert( ExprUseYTab(pExpr) ); pExTab = pExpr->y.pTab; assert( pExTab!=0 ); + assert( n < pExTab->nCol ); +#ifdef MAGMA_ENABLE_FIXES if( (pExTab->tabFlags & TF_HasGenerated)!=0 - && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 + && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0 ){ testcase( pExTab->nCol==BMS-1 ); testcase( pExTab->nCol==BMS ); @@ -33,8 +35,7 @@ index e90e8a768..654bf133e 100644 + MAGMA_LOG("%MAGMA_BUG%", + MAGMA_AND((pExTab->tabFlags & TF_HasGenerated)!=0, + MAGMA_AND((pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0, -+ MAGMA_AND(pExTab->nCol >= BMS, -+ result < ALLBITS))) ++ MAGMA_AND(pExTab->nCol >= BMS, result < ALLBITS))) + ); +#endif +#endif diff --git a/targets/sqlite3/patches/bugs/SQL017.patch b/targets/sqlite3/patches/bugs/SQL017.patch new file mode 100644 index 000000000..e47dd0cbe --- /dev/null +++ b/targets/sqlite3/patches/bugs/SQL017.patch @@ -0,0 +1,57 @@ +diff --git a/src/expr.c b/src/expr.c +index 86c966683c..6ccde06009 100644 +--- a/src/expr.c ++++ b/src/expr.c +@@ -6670,13 +6670,26 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + ** impliesNotNullRow() test */ + assert( pLeft->op!=TK_COLUMN || ExprUseYTab(pLeft) ); + assert( pRight->op!=TK_COLUMN || ExprUseYTab(pRight) ); ++#ifdef MAGMA_ENABLE_FIXES + if( (pLeft->op==TK_COLUMN + && ALWAYS(pLeft->y.pTab!=0) + && IsVirtual(pLeft->y.pTab)) + || (pRight->op==TK_COLUMN + && ALWAYS(pRight->y.pTab!=0) + && IsVirtual(pRight->y.pTab)) +- ){ ++ ) ++#else ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR( ++ MAGMA_AND(pLeft->op==TK_COLUMN, pLeft->y.pTab == 0), ++ MAGMA_AND(pLeft->op!=TK_COLUMN, ++ MAGMA_AND(pRight->op==TK_COLUMN, pRight->y.pTab == 0)))); ++#endif ++ if( (pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab)) ++ || (pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab)) ++ ) ++#endif ++ { + return WRC_Prune; + } + /* no break */ deliberate_fall_through +diff --git a/src/sqliteInt.h b/src/sqliteInt.h +index b8c9136a59..d0e9ce8178 100644 +--- a/src/sqliteInt.h ++++ b/src/sqliteInt.h +@@ -2471,9 +2471,20 @@ struct Table { + */ + #ifndef SQLITE_OMIT_VIRTUALTABLE + # define IsVirtual(X) ((X)->eTabType==TABTYP_VTAB) ++#ifdef MAGMA_ENABLE_FIXES + # define ExprIsVtab(X) \ + ((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB) + #else ++#ifdef MAGMA_ENABLE_CANARIES ++# define ExprIsVtab(X) \ ++ (MAGMA_LOG_V("%MAGMA_BUG%", MAGMA_AND((X)->op==TK_COLUMN, (X)->y.pTab == 0)), \ ++ (X)->op==TK_COLUMN && (X)->y.pTab->eTabType) ++#else ++# define ExprIsVtab(X) \ ++ ((X)->op==TK_COLUMN && (X)->y.pTab==0) ++#endif ++#endif ++#else + # define IsVirtual(X) 0 + # define ExprIsVtab(X) 0 + #endif diff --git a/targets/sqlite3/patches/failed/bugs/SQL003.patch b/targets/sqlite3/patches/failed/bugs/SQL003.patch deleted file mode 100644 index 0e36c3da6..000000000 --- a/targets/sqlite3/patches/failed/bugs/SQL003.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/src/select.c b/src/select.c -index a9ec1e852..ad955b5de 100644 ---- a/src/select.c -+++ b/src/select.c -@@ -3827,10 +3827,15 @@ static int flattenSubquery( - if( pSubSrc->nSrc>1 /* (3a) */ - || isAgg /* (3b) */ - || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */ -+#ifdef MAGMA_ENABLE_FIXES - || (p->selFlags & SF_Distinct)!=0 /* (3d) */ -+#endif - ){ - return 0; - } -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (p->selFlags & SF_Distinct)!=0); -+#endif - } - #ifdef SQLITE_EXTRA_IFNULLROW - else if( iFrom>0 && !isAgg ){ diff --git a/targets/sqlite3/patches/failed/bugs/SQL012.patch b/targets/sqlite3/patches/failed/bugs/SQL012.patch deleted file mode 100644 index 79ccf77c9..000000000 --- a/targets/sqlite3/patches/failed/bugs/SQL012.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/src/pragma.c b/src/pragma.c -index c5b5bb667..a882e2307 100644 ---- a/src/pragma.c -+++ b/src/pragma.c -@@ -1645,9 +1645,17 @@ void sqlite3Pragma( - if( j==pTab->iPKey ) continue; - if( pTab->aCol[j].notNull==0 ) continue; - sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); -+#ifndef MAGMA_ENABLE_FIXES -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", sqlite3VdbeGetOp(v,-1)->opcode!=OP_Column); -+#endif -+#else - if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ -+#endif - sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); -+#ifdef MAGMA_ENABLE_FIXES - } -+#endif - jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); - zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, - pTab->aCol[j].zName); diff --git a/targets/sqlite3/patches/failed/bugs/SQL017.patch b/targets/sqlite3/patches/failed/bugs/SQL017.patch deleted file mode 100644 index 92c6b6848..000000000 --- a/targets/sqlite3/patches/failed/bugs/SQL017.patch +++ /dev/null @@ -1,55 +0,0 @@ -diff --git a/src/expr.c b/src/expr.c -index 8587f5ec7..225ee6737 100644 ---- a/src/expr.c -+++ b/src/expr.c -@@ -5514,11 +5514,24 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ - testcase( pExpr->op==TK_GE ); - /* The y.pTab=0 assignment in wherecode.c always happens after the - ** impliesNotNullRow() test */ -+#ifdef MAGMA_ENABLE_FIXES - if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0) - && IsVirtual(pLeft->y.pTab)) - || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0) - && IsVirtual(pRight->y.pTab)) -- ){ -+ ) -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR( -+ MAGMA_AND(pLeft->op==TK_COLUMN, pLeft->y.pTab == 0), -+ MAGMA_AND(pLeft->op!=TK_COLUMN, -+ MAGMA_AND(pRight->op==TK_COLUMN, pRight->y.pTab == 0)))); -+#endif -+ if( (pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab)) -+ || (pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab)) -+ ) -+#endif -+ { - return WRC_Prune; - } - } -diff --git a/src/sqliteInt.h b/src/sqliteInt.h -index 7a00b576a..9e7d21b7f 100644 ---- a/src/sqliteInt.h -+++ b/src/sqliteInt.h -@@ -2153,9 +2153,20 @@ struct Table { - */ - #ifndef SQLITE_OMIT_VIRTUALTABLE - # define IsVirtual(X) ((X)->nModuleArg) -+#ifdef MAGMA_ENABLE_FIXES - # define ExprIsVtab(X) \ - ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg) - #else -+#ifdef MAGMA_ENABLE_CANARIES -+# define ExprIsVtab(X) \ -+ (MAGMA_LOG_V("%MAGMA_BUG%", MAGMA_AND((X)->op==TK_COLUMN, (X)->y.pTab == 0)), \ -+ (X)->op==TK_COLUMN && (X)->y.pTab->nModuleArg) -+#else -+# define ExprIsVtab(X) \ -+ ((X)->op==TK_COLUMN && (X)->y.pTab==0) -+#endif -+#endif -+#else - # define IsVirtual(X) 0 - # define ExprIsVtab(X) 0 - #endif diff --git a/targets/sqlite3/patches/graveyard/SQL012.patch b/targets/sqlite3/patches/graveyard/SQL012.patch new file mode 100644 index 000000000..1b5a426d8 --- /dev/null +++ b/targets/sqlite3/patches/graveyard/SQL012.patch @@ -0,0 +1,42 @@ +# The logic behind this bug is to disable the following guard in the sqlite3Pragma functionality: +# - Only set the P5 flag if the last VDBE instruction was an OP_Column; otherwise, leave it unmodified. +# But in the updated code, in addtion to new logic that handles virtual tables, there is this snippet +# (https://github.com/sqlite/sqlite/blob/d7324103b196c572a98724a5658970b4000b8c39/src/pragma.c#L1861): + +# /* make sure there actually is a real column to fetch before emitting the two preparatory opcodes */ +# if( mxCol>=0 ){ +# // OP_Column will parse the entire record header, which sanity-checks the blob format +# // and fills the column cache for cursor iDataCur. +# sqlite3VdbeAddOp3(v, OP_Column, iDataCur, mxCol, 3); +# // sqlite3VdbeTypeofColumn(v,3) emits OP_Typeof, which reads that freshly-cached column into register +# sqlite3VdbeTypeofColumn(v, 3); +# // After these two ops, the “last opcode” is always OP_Column. +# } + +# The only time OP_Column ever appears is deep inside the “NaN-fixup” path (p1<0 case), and they no +# longer bother checking "did I just emit an OP_Column?" since it is unconditionally emitted. + +# Therefore the patch is no longer applicable on the current codebase. + +diff --git a/src/pragma.c b/src/pragma.c +index c5b5bb667..a882e2307 100644 +--- a/src/pragma.c ++++ b/src/pragma.c +@@ -1645,9 +1645,17 @@ void sqlite3Pragma( + if( j==pTab->iPKey ) continue; + if( pTab->aCol[j].notNull==0 ) continue; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); ++#ifndef MAGMA_ENABLE_FIXES ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", sqlite3VdbeGetOp(v,-1)->opcode!=OP_Column); ++#endif ++#else + if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ ++#endif + sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); ++#ifdef MAGMA_ENABLE_FIXES + } ++#endif + jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); + zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, + pTab->aCol[j].zName); diff --git a/targets/sqlite3/patches/failed/bugs/SQL019.patch b/targets/sqlite3/patches/graveyard/SQL019.patch similarity index 56% rename from targets/sqlite3/patches/failed/bugs/SQL019.patch rename to targets/sqlite3/patches/graveyard/SQL019.patch index ec04a97ad..bb196be7a 100644 --- a/targets/sqlite3/patches/failed/bugs/SQL019.patch +++ b/targets/sqlite3/patches/graveyard/SQL019.patch @@ -1,3 +1,15 @@ +# In this bug, if one passed a huge precision, we would get a correspondingly huge idx and an equally +# large loop of while(idx >= 10). +# However, in the new code, the rounding logic is moved to sqlite3FpDecode in src/util.c and also isolated +# from the precision value itself. +# (https://github.com/sqlite/sqlite/blob/d7324103b196c572a98724a5658970b4000b8c39/src/util.c#L1017) +# There is no idx = precision; while(idx>=10){} construct in the new floating-point decoder. sqlite3FpDecode +# uses the iRound and mxRound variables for the rounding process. So, even if precision is huge, iRound is +# forced down to 16 or 26, and we you never iterate more than that many digits. Furthermore, While +# szBufNeeded can grow, it only affects allocation size and not the core decode/round performance or buffer safety. + +# Therefore the patch is no longer applicable on the current codebase. + diff --git a/src/printf.c b/src/printf.c index fc77f68df..a22223d75 100644 --- a/src/printf.c From 8db709e0dffd842a9f9d7894b34a8d63123145ef Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Mon, 5 May 2025 12:40:06 +0200 Subject: [PATCH 073/150] Port 3 bugs for libtff --- targets/libtiff/patches/bugs/TIF001.patch | 178 +++++++++++++++++ targets/libtiff/patches/bugs/TIF006.patch | 26 +++ targets/libtiff/patches/bugs/TIF010.patch | 21 ++ .../libtiff/patches/failed/bugs/TIF001.patch | 189 ------------------ .../libtiff/patches/failed/bugs/TIF006.patch | 27 --- .../libtiff/patches/failed/bugs/TIF010.patch | 21 -- 6 files changed, 225 insertions(+), 237 deletions(-) create mode 100644 targets/libtiff/patches/bugs/TIF001.patch create mode 100644 targets/libtiff/patches/bugs/TIF006.patch create mode 100644 targets/libtiff/patches/bugs/TIF010.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF001.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF006.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF010.patch diff --git a/targets/libtiff/patches/bugs/TIF001.patch b/targets/libtiff/patches/bugs/TIF001.patch new file mode 100644 index 000000000..13f58d45f --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF001.patch @@ -0,0 +1,178 @@ +diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c +index 386b5fe8..23b3be07 100644 +--- a/libtiff/tif_predict.c ++++ b/libtiff/tif_predict.c +@@ -344,11 +344,16 @@ static int horAcc8(TIFF *tif, uint8_t *cp0, tmsize_t cc) + tmsize_t stride = PredictorState(tif)->stride; + + unsigned char *cp = (unsigned char *)cp0; ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % stride) != 0) + { + TIFFErrorExtR(tif, "horAcc8", "%s", "(cc%stride)!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%stride)!=0); ++#endif + + if (cc > stride) + { +@@ -414,11 +419,16 @@ static int horAcc16(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint16_t *wp = (uint16_t *)cp0; + tmsize_t wc = cc / 2; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % (2 * stride)) != 0) + { + TIFFErrorExtR(tif, "horAcc16", "%s", "cc%(2*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(2*stride))!=0); ++#endif + + if (wc > stride) + { +@@ -451,11 +461,16 @@ static int horAcc32(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint32_t *wp = (uint32_t *)cp0; + tmsize_t wc = cc / 4; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % (4 * stride)) != 0) + { + TIFFErrorExtR(tif, "horAcc32", "%s", "cc%(4*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(4*stride))!=0); ++#endif + + if (wc > stride) + { +@@ -515,11 +530,16 @@ static int fpAcc(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint8_t *cp = (uint8_t *)cp0; + uint8_t *tmp; + ++#ifdef MAGMA_ENABLE_FIXES + if (cc % (bps * stride) != 0) + { + TIFFErrorExtR(tif, "fpAcc", "%s", "cc%(bps*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(bps*stride))!=0); ++#endif + + tmp = (uint8_t *)_TIFFmallocExt(tif, cc); + if (!tmp) +@@ -590,12 +610,17 @@ static int PredictorDecodeTile(TIFF *tif, uint8_t *op0, tmsize_t occ0, + { + tmsize_t rowsize = sp->rowsize; + assert(rowsize > 0); ++#ifdef MAGMA_ENABLE_FIXES + if ((occ0 % rowsize) != 0) + { + TIFFErrorExtR(tif, "PredictorDecodeTile", "%s", + "occ0%rowsize != 0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (occ0%rowsize)!=0); ++#endif + assert(sp->decodepfunc != NULL); + while (occ0 > 0) + { +@@ -617,11 +642,16 @@ static int horDiff8(TIFF *tif, uint8_t *cp0, tmsize_t cc) + tmsize_t stride = sp->stride; + unsigned char *cp = (unsigned char *)cp0; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % stride) != 0) + { + TIFFErrorExtR(tif, "horDiff8", "%s", "(cc%stride)!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%stride)!=0); ++#endif + + if (cc > stride) + { +@@ -696,11 +726,16 @@ static int horDiff16(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint16_t *wp = (uint16_t *)cp0; + tmsize_t wc = cc / 2; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % (2 * stride)) != 0) + { + TIFFErrorExtR(tif, "horDiff8", "%s", "(cc%(2*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(2*stride))!=0); ++#endif + + if (wc > stride) + { +@@ -738,11 +773,16 @@ static int horDiff32(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint32_t *wp = (uint32_t *)cp0; + tmsize_t wc = cc / 4; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % (4 * stride)) != 0) + { + TIFFErrorExtR(tif, "horDiff32", "%s", "(cc%(4*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(4*stride))!=0); ++#endif + + if (wc > stride) + { +@@ -821,11 +861,16 @@ static int fpDiff(TIFF *tif, uint8_t *cp0, tmsize_t cc) + uint8_t *cp = (uint8_t *)cp0; + uint8_t *tmp; + ++#ifdef MAGMA_ENABLE_FIXES + if ((cc % (bps * stride)) != 0) + { + TIFFErrorExtR(tif, "fpDiff", "%s", "(cc%(bps*stride))!=0"); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc%(bps*stride))!=0); ++#endif + + tmp = (uint8_t *)_TIFFmallocExt(tif, cc); + if (!tmp) +@@ -900,12 +945,19 @@ static int PredictorEncodeTile(TIFF *tif, uint8_t *bp0, tmsize_t cc0, + + rowsize = sp->rowsize; + assert(rowsize > 0); ++ ++#ifdef MAGMA_ENABLE_FIXES + if ((cc0 % rowsize) != 0) + { + TIFFErrorExtR(tif, "PredictorEncodeTile", "%s", "(cc0%rowsize)!=0"); + _TIFFfreeExt(tif, working_copy); + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (cc0%rowsize)!=0); ++#endif ++ + while (cc > 0) + { + (*sp->encodepfunc)(tif, bp, rowsize); diff --git a/targets/libtiff/patches/bugs/TIF006.patch b/targets/libtiff/patches/bugs/TIF006.patch new file mode 100644 index 000000000..893061f6f --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF006.patch @@ -0,0 +1,26 @@ +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index 5ed921eb..956514e4 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -1449,8 +1449,9 @@ static void PixarLogClose(TIFF *tif) + * readers that don't know about PixarLog, or how to set + * the PIXARLOGDATFMT pseudo-tag. + */ +- +- if (sp->state & PLSTATE_INIT) ++#ifdef MAGMA_ENABLE_FIXES ++ if (sp->state&PLSTATE_INIT) ++#endif + { + /* We test the state to avoid an issue such as in + * http://bugzilla.maptools.org/show_bug.cgi?id=2604 +@@ -1463,6 +1464,9 @@ static void PixarLogClose(TIFF *tif) + td->td_bitspersample = 8; + td->td_sampleformat = SAMPLEFORMAT_UINT; + } ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (sp->state&PLSTATE_INIT) == 0); ++#endif + } + + static void PixarLogCleanup(TIFF *tif) diff --git a/targets/libtiff/patches/bugs/TIF010.patch b/targets/libtiff/patches/bugs/TIF010.patch new file mode 100644 index 000000000..181ccdfb7 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF010.patch @@ -0,0 +1,21 @@ +diff --git a/libtiff/tif_lzw.c b/libtiff/tif_lzw.c +index 05ac8aa1..b9b0e9b9 100644 +--- a/libtiff/tif_lzw.c ++++ b/libtiff/tif_lzw.c +@@ -973,9 +973,16 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) + tp = op + len; + do + { ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", tp <= op); // or use == instead of <= so the bug is reported once only ++#endif + *--tp = codep->value; + codep = codep->next; ++#ifdef MAGMA_ENABLE_FIXES + } while (codep && tp > op); ++#else ++ } while (codep); ++#endif + assert(occ >= len); + op += len; + occ -= len; diff --git a/targets/libtiff/patches/failed/bugs/TIF001.patch b/targets/libtiff/patches/failed/bugs/TIF001.patch deleted file mode 100644 index 66adb3a7a..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF001.patch +++ /dev/null @@ -1,189 +0,0 @@ -diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c -index b775663..98d7c6b 100644 ---- a/libtiff/tif_predict.c -+++ b/libtiff/tif_predict.c -@@ -282,12 +282,17 @@ horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc) - tmsize_t stride = PredictorState(tif)->stride; - - unsigned char* cp = (unsigned char*) cp0; -+#ifdef MAGMA_ENABLE_FIXES - if((cc%stride)!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horAcc8", - "%s", "(cc%stride)!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%stride)!=0); -+#endif - - if (cc > stride) { - /* -@@ -351,12 +356,17 @@ horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc) - uint16* wp = (uint16*) cp0; - tmsize_t wc = cc / 2; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%(2*stride))!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horAcc16", - "%s", "cc%(2*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(2*stride))!=0); -+#endif - - if (wc > stride) { - wc -= stride; -@@ -386,12 +396,17 @@ horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc) - uint32* wp = (uint32*) cp0; - tmsize_t wc = cc / 4; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%(4*stride))!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horAcc32", - "%s", "cc%(4*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(4*stride))!=0); -+#endif - - if (wc > stride) { - wc -= stride; -@@ -416,12 +431,17 @@ fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc) - uint8 *cp = (uint8 *) cp0; - uint8 *tmp; - -+#ifdef MAGMA_ENABLE_FIXES - if(cc%(bps*stride)!=0) - { - TIFFErrorExt(tif->tif_clientdata, "fpAcc", - "%s", "cc%(bps*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(bps*stride))!=0); -+#endif - - tmp = (uint8 *)_TIFFmalloc(cc); - if (!tmp) -@@ -486,12 +506,19 @@ PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) - if ((*sp->decodetile)(tif, op0, occ0, s)) { - tmsize_t rowsize = sp->rowsize; - assert(rowsize > 0); -+ -+#ifdef MAGMA_ENABLE_FIXES - if((occ0%rowsize) !=0) - { - TIFFErrorExt(tif->tif_clientdata, "PredictorDecodeTile", - "%s", "occ0%rowsize != 0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (occ0%rowsize)!=0); -+#endif -+ - assert(sp->decodepfunc != NULL); - while (occ0 > 0) { - if( !(*sp->decodepfunc)(tif, op0, rowsize) ) -@@ -512,12 +539,17 @@ horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc) - tmsize_t stride = sp->stride; - unsigned char* cp = (unsigned char*) cp0; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%stride)!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horDiff8", - "%s", "(cc%stride)!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%stride)!=0); -+#endif - - if (cc > stride) { - cc -= stride; -@@ -567,12 +599,17 @@ horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc) - uint16 *wp = (uint16*) cp0; - tmsize_t wc = cc/2; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%(2*stride))!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horDiff8", - "%s", "(cc%(2*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(2*stride))!=0); -+#endif - - if (wc > stride) { - wc -= stride; -@@ -607,12 +644,17 @@ horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc) - uint32 *wp = (uint32*) cp0; - tmsize_t wc = cc/4; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%(4*stride))!=0) - { - TIFFErrorExt(tif->tif_clientdata, "horDiff32", - "%s", "(cc%(4*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(4*stride))!=0); -+#endif - - if (wc > stride) { - wc -= stride; -@@ -652,12 +694,17 @@ fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc) - uint8 *cp = (uint8 *) cp0; - uint8 *tmp; - -+#ifdef MAGMA_ENABLE_FIXES - if((cc%(bps*stride))!=0) - { - TIFFErrorExt(tif->tif_clientdata, "fpDiff", - "%s", "(cc%(bps*stride))!=0"); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc%(bps*stride))!=0); -+#endif - - tmp = (uint8 *)_TIFFmalloc(cc); - if (!tmp) -@@ -730,6 +777,8 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s) - - rowsize = sp->rowsize; - assert(rowsize > 0); -+ -+#ifdef MAGMA_ENABLE_FIXES - if((cc0%rowsize)!=0) - { - TIFFErrorExt(tif->tif_clientdata, "PredictorEncodeTile", -@@ -737,6 +786,11 @@ PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s) - _TIFFfree( working_copy ); - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (cc0%rowsize)!=0); -+#endif -+ - while (cc > 0) { - (*sp->encodepfunc)(tif, bp, rowsize); - cc -= rowsize; diff --git a/targets/libtiff/patches/failed/bugs/TIF006.patch b/targets/libtiff/patches/failed/bugs/TIF006.patch deleted file mode 100644 index 224cfc6c2..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF006.patch +++ /dev/null @@ -1,27 +0,0 @@ -diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c -index b1e48d9..1c14581 100644 ---- a/libtiff/tif_pixarlog.c -+++ b/libtiff/tif_pixarlog.c -@@ -1265,8 +1265,10 @@ PixarLogClose(TIFF* tif) - * readers that don't know about PixarLog, or how to set - * the PIXARLOGDATFMT pseudo-tag. - */ -- -- if (sp->state&PLSTATE_INIT) { -+#ifdef MAGMA_ENABLE_FIXES -+ if (sp->state&PLSTATE_INIT) -+#endif -+ { - /* We test the state to avoid an issue such as in - * http://bugzilla.maptools.org/show_bug.cgi?id=2604 - * What appends in that case is that the bitspersample is 1 and -@@ -1278,6 +1280,9 @@ PixarLogClose(TIFF* tif) - td->td_bitspersample = 8; - td->td_sampleformat = SAMPLEFORMAT_UINT; - } -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (sp->state&PLSTATE_INIT) == 0); -+#endif - } - - static void diff --git a/targets/libtiff/patches/failed/bugs/TIF010.patch b/targets/libtiff/patches/failed/bugs/TIF010.patch deleted file mode 100644 index f1f81e684..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF010.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/libtiff/tif_lzw.c b/libtiff/tif_lzw.c -index 21064f2..fb63a80 100644 ---- a/libtiff/tif_lzw.c -+++ b/libtiff/tif_lzw.c -@@ -764,9 +764,16 @@ LZWDecodeCompat(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s) - len = codep->length; - tp = op + len; - do { -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", tp <= op); // or use == instead of <= so the bug is reported once only -+#endif - *--tp = codep->value; - codep = codep->next; -+#ifdef MAGMA_ENABLE_FIXES - } while (codep && tp > op); -+#else -+ } while (codep); -+#endif - assert(occ >= len); - op += len; - occ -= len; From 4b542d10b6780cbd38b18498c90a271c2bb865f6 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Mon, 5 May 2025 14:25:48 +0200 Subject: [PATCH 074/150] Port bugs for PHP --- .../patches/{failed => }/bugs/PHP010.patch | 0 targets/php/patches/bugs/PHP012.patch | 31 +++++++++++++++++++ .../patches/{failed => }/bugs/PHP015.patch | 0 targets/php/patches/failed/bugs/PHP012.patch | 30 ------------------ 4 files changed, 31 insertions(+), 30 deletions(-) rename targets/php/patches/{failed => }/bugs/PHP010.patch (100%) create mode 100644 targets/php/patches/bugs/PHP012.patch rename targets/php/patches/{failed => }/bugs/PHP015.patch (100%) delete mode 100644 targets/php/patches/failed/bugs/PHP012.patch diff --git a/targets/php/patches/failed/bugs/PHP010.patch b/targets/php/patches/bugs/PHP010.patch similarity index 100% rename from targets/php/patches/failed/bugs/PHP010.patch rename to targets/php/patches/bugs/PHP010.patch diff --git a/targets/php/patches/bugs/PHP012.patch b/targets/php/patches/bugs/PHP012.patch new file mode 100644 index 000000000..9a152b672 --- /dev/null +++ b/targets/php/patches/bugs/PHP012.patch @@ -0,0 +1,31 @@ +diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c +index fff6af5e214..9c63f400d3e 100644 +--- a/ext/standard/http_fopen_wrapper.c ++++ b/ext/standard/http_fopen_wrapper.c +@@ -723,6 +723,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, + tmp_line, response_code); + } + } ++ #ifdef MAGMA_ENABLE_FIXES + if (tmp_line_len >= 1 && tmp_line[tmp_line_len - 1] == '\n') { + --tmp_line_len; + if (tmp_line_len >= 1 &&tmp_line[tmp_line_len - 1] == '\r') { +@@ -733,6 +734,18 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, + char *line = php_stream_get_line(stream, NULL, 0, NULL); + efree(line); + } ++ #else ++ #ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", tmp_line_len < 1); ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(tmp_line_len == 1, tmp_line[tmp_line_len - 1] == '\n')); ++ #endif ++ if (tmp_line[tmp_line_len - 1] == '\n') { ++ --tmp_line_len; ++ if (tmp_line[tmp_line_len - 1] == '\r') { ++ --tmp_line_len; ++ } ++ } ++ #endif + ZVAL_STRINGL(&http_response, tmp_line, tmp_line_len); + zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response); + } else { diff --git a/targets/php/patches/failed/bugs/PHP015.patch b/targets/php/patches/bugs/PHP015.patch similarity index 100% rename from targets/php/patches/failed/bugs/PHP015.patch rename to targets/php/patches/bugs/PHP015.patch diff --git a/targets/php/patches/failed/bugs/PHP012.patch b/targets/php/patches/failed/bugs/PHP012.patch deleted file mode 100644 index 7960edcdd..000000000 --- a/targets/php/patches/failed/bugs/PHP012.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c -index ae9b915101..c3d64424f3 100644 ---- a/ext/standard/http_fopen_wrapper.c -+++ b/ext/standard/http_fopen_wrapper.c -@@ -712,12 +712,25 @@ finish: - tmp_line, response_code); - } - } -+ #ifdef MAGMA_ENABLE_FIXES - if (tmp_line_len >= 1 && tmp_line[tmp_line_len - 1] == '\n') { - --tmp_line_len; - if (tmp_line_len >= 1 &&tmp_line[tmp_line_len - 1] == '\r') { - --tmp_line_len; - } - } -+ #else -+ #ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", tmp_line_len < 1); -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(tmp_line_len == 1, tmp_line[tmp_line_len - 1] == '\n')); -+ #endif -+ if (tmp_line[tmp_line_len - 1] == '\n') { -+ --tmp_line_len; -+ if (tmp_line[tmp_line_len - 1] == '\r') { -+ --tmp_line_len; -+ } -+ } -+ #endif - ZVAL_STRINGL(&http_response, tmp_line, tmp_line_len); - zend_hash_next_index_insert(Z_ARRVAL_P(response_header), &http_response); - } else { From 68b1dddfd2f859d4d1214c15b2b1f933b212240f Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 7 May 2025 12:41:02 +0200 Subject: [PATCH 075/150] Add some more details in sqlite3 graveyard patches --- targets/sqlite3/patches/graveyard/SQL012.patch | 6 +++++- targets/sqlite3/patches/graveyard/SQL019.patch | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/targets/sqlite3/patches/graveyard/SQL012.patch b/targets/sqlite3/patches/graveyard/SQL012.patch index 1b5a426d8..19b07a9a6 100644 --- a/targets/sqlite3/patches/graveyard/SQL012.patch +++ b/targets/sqlite3/patches/graveyard/SQL012.patch @@ -1,3 +1,7 @@ +# Codebase versions used for the following explaination: +# 1. Old code: sqlite3Pragma in pragma.c (tarball: https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=8c432642572c8c4b) +# 2. New code: sqlite3Pragma in pragma.c (commit: 66985fb8fff34b7d46980202b9a245f3bb9db26a) + # The logic behind this bug is to disable the following guard in the sqlite3Pragma functionality: # - Only set the P5 flag if the last VDBE instruction was an OP_Column; otherwise, leave it unmodified. # But in the updated code, in addtion to new logic that handles virtual tables, there is this snippet @@ -16,7 +20,7 @@ # The only time OP_Column ever appears is deep inside the “NaN-fixup” path (p1<0 case), and they no # longer bother checking "did I just emit an OP_Column?" since it is unconditionally emitted. -# Therefore the patch is no longer applicable on the current codebase. +# Therefore the patch is no longer applicable on the current codebase and cannot be updated without backporting. diff --git a/src/pragma.c b/src/pragma.c index c5b5bb667..a882e2307 100644 diff --git a/targets/sqlite3/patches/graveyard/SQL019.patch b/targets/sqlite3/patches/graveyard/SQL019.patch index bb196be7a..2e2da17c5 100644 --- a/targets/sqlite3/patches/graveyard/SQL019.patch +++ b/targets/sqlite3/patches/graveyard/SQL019.patch @@ -1,3 +1,7 @@ +# Codebase versions used for the following explaination: +# 1. Old code: sqlite3_str_vappendf in printf.c (tarball: https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=8c432642572c8c4b) +# 2. New code: sqlite3FpDecode in util.c (commit: 66985fb8fff34b7d46980202b9a245f3bb9db26a) + # In this bug, if one passed a huge precision, we would get a correspondingly huge idx and an equally # large loop of while(idx >= 10). # However, in the new code, the rounding logic is moved to sqlite3FpDecode in src/util.c and also isolated @@ -8,7 +12,7 @@ # forced down to 16 or 26, and we you never iterate more than that many digits. Furthermore, While # szBufNeeded can grow, it only affects allocation size and not the core decode/round performance or buffer safety. -# Therefore the patch is no longer applicable on the current codebase. +# Therefore the patch is no longer applicable on the current codebase and cannot be updated without backporting. diff --git a/src/printf.c b/src/printf.c index fc77f68df..a22223d75 100644 From 579c79240c4ab585359c75151c6851530fdb9d2b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 8 May 2025 11:09:41 +0200 Subject: [PATCH 076/150] Flag deprecated libxml2 bugs --- targets/libxml2/patches/failed/bugs/XML002.patch | 2 ++ targets/libxml2/patches/failed/bugs/XML003.patch | 2 ++ targets/libxml2/patches/failed/bugs/XML005.patch | 2 ++ targets/libxml2/patches/failed/bugs/XML008.patch | 2 ++ targets/libxml2/patches/failed/bugs/XML009.patch | 2 ++ targets/libxml2/patches/failed/bugs/XML010.patch | 2 ++ 6 files changed, 12 insertions(+) diff --git a/targets/libxml2/patches/failed/bugs/XML002.patch b/targets/libxml2/patches/failed/bugs/XML002.patch index 594802b46..c668fd39d 100644 --- a/targets/libxml2/patches/failed/bugs/XML002.patch +++ b/targets/libxml2/patches/failed/bugs/XML002.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 diff --git a/valid.c b/valid.c index b1cfede..49e6251 100644 --- a/valid.c diff --git a/targets/libxml2/patches/failed/bugs/XML003.patch b/targets/libxml2/patches/failed/bugs/XML003.patch index ad87561fe..af3f142ad 100644 --- a/targets/libxml2/patches/failed/bugs/XML003.patch +++ b/targets/libxml2/patches/failed/bugs/XML003.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 diff --git a/parser.c b/parser.c index 04aa717..579a9a7 100644 --- a/parser.c diff --git a/targets/libxml2/patches/failed/bugs/XML005.patch b/targets/libxml2/patches/failed/bugs/XML005.patch index c3c773823..9eb450a1e 100644 --- a/targets/libxml2/patches/failed/bugs/XML005.patch +++ b/targets/libxml2/patches/failed/bugs/XML005.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 --- a/xmlmemory.c +++ b/xmlmemory.c @@ -172,12 +172,17 @@ xmlMallocLoc(size_t size, const char * file, int line) diff --git a/targets/libxml2/patches/failed/bugs/XML008.patch b/targets/libxml2/patches/failed/bugs/XML008.patch index 142bfaf10..4be9a1dba 100644 --- a/targets/libxml2/patches/failed/bugs/XML008.patch +++ b/targets/libxml2/patches/failed/bugs/XML008.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 diff --git a/parser.c b/parser.c index 3f31329..b3e1429 100644 --- a/parser.c diff --git a/targets/libxml2/patches/failed/bugs/XML009.patch b/targets/libxml2/patches/failed/bugs/XML009.patch index 169b3ed17..bd37fde25 100644 --- a/targets/libxml2/patches/failed/bugs/XML009.patch +++ b/targets/libxml2/patches/failed/bugs/XML009.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 diff --git a/parser.c b/parser.c index 3f31329..ff89bb7 100644 --- a/parser.c diff --git a/targets/libxml2/patches/failed/bugs/XML010.patch b/targets/libxml2/patches/failed/bugs/XML010.patch index e772b5547..742f4aba6 100644 --- a/targets/libxml2/patches/failed/bugs/XML010.patch +++ b/targets/libxml2/patches/failed/bugs/XML010.patch @@ -1,3 +1,5 @@ +# This bug is applied on functions that are now deprecated, therefore it does not make sense to include +# it in magma anymore since it will likely not be triggered at all by the latest version of libxml2 diff --git a/parser.c b/parser.c index 3f31329..db7f7d1 100644 --- a/parser.c From e0d27c6c59e3cdd4701006a88bea34946e9b3e40 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sun, 11 May 2025 18:49:23 +0200 Subject: [PATCH 077/150] Port bugs for libxml --- .../patches/{failed => }/bugs/XML011.patch | 36 ++++++------- targets/libxml2/patches/bugs/XML012.patch | 42 +++++++++++++++ targets/libxml2/patches/bugs/XML015.patch | 39 ++++++++++++++ .../patches/{failed => }/bugs/XML017.patch | 6 +-- .../libxml2/patches/failed/bugs/XML007.patch | 31 ----------- .../libxml2/patches/failed/bugs/XML012.patch | 51 ------------------ .../libxml2/patches/failed/bugs/XML014.patch | 18 ------- .../libxml2/patches/failed/bugs/XML015.patch | 23 -------- .../{failed/bugs => graveyard}/XML002.patch | 0 .../{failed/bugs => graveyard}/XML003.patch | 0 .../{failed/bugs => graveyard}/XML005.patch | 0 .../libxml2/patches/graveyard/XML007.patch | 52 +++++++++++++++++++ .../{failed/bugs => graveyard}/XML008.patch | 0 .../{failed/bugs => graveyard}/XML009.patch | 0 .../{failed/bugs => graveyard}/XML010.patch | 0 .../{failed/bugs => graveyard}/XML013.patch | 18 +++++++ .../libxml2/patches/graveyard/XML014.patch | 39 ++++++++++++++ 17 files changed, 210 insertions(+), 145 deletions(-) rename targets/libxml2/patches/{failed => }/bugs/XML011.patch (58%) create mode 100644 targets/libxml2/patches/bugs/XML012.patch create mode 100644 targets/libxml2/patches/bugs/XML015.patch rename targets/libxml2/patches/{failed => }/bugs/XML017.patch (82%) delete mode 100644 targets/libxml2/patches/failed/bugs/XML007.patch delete mode 100644 targets/libxml2/patches/failed/bugs/XML012.patch delete mode 100644 targets/libxml2/patches/failed/bugs/XML014.patch delete mode 100644 targets/libxml2/patches/failed/bugs/XML015.patch rename targets/libxml2/patches/{failed/bugs => graveyard}/XML002.patch (100%) rename targets/libxml2/patches/{failed/bugs => graveyard}/XML003.patch (100%) rename targets/libxml2/patches/{failed/bugs => graveyard}/XML005.patch (100%) create mode 100644 targets/libxml2/patches/graveyard/XML007.patch rename targets/libxml2/patches/{failed/bugs => graveyard}/XML008.patch (100%) rename targets/libxml2/patches/{failed/bugs => graveyard}/XML009.patch (100%) rename targets/libxml2/patches/{failed/bugs => graveyard}/XML010.patch (100%) rename targets/libxml2/patches/{failed/bugs => graveyard}/XML013.patch (66%) create mode 100644 targets/libxml2/patches/graveyard/XML014.patch diff --git a/targets/libxml2/patches/failed/bugs/XML011.patch b/targets/libxml2/patches/bugs/XML011.patch similarity index 58% rename from targets/libxml2/patches/failed/bugs/XML011.patch rename to targets/libxml2/patches/bugs/XML011.patch index c53537ad8..e56b1edad 100644 --- a/targets/libxml2/patches/failed/bugs/XML011.patch +++ b/targets/libxml2/patches/bugs/XML011.patch @@ -1,19 +1,19 @@ diff --git a/xmlstring.c b/xmlstring.c -index 8d2e06f..5715bb0 100644 +index 5f03e07a..899e96cc 100644 --- a/xmlstring.c +++ b/xmlstring.c -@@ -457,13 +457,21 @@ xmlStrncat(xmlChar *cur, const xmlChar *add, int len) { +@@ -465,13 +465,21 @@ xmlStrncat(xmlChar *cur, const xmlChar *add, int len) { return(xmlStrndup(add, len)); size = xmlStrlen(cur); +#ifdef MAGMA_ENABLE_FIXES - if (size < 0) + if ((size < 0) || (size > INT_MAX - len)) return(NULL); +#endif - ret = (xmlChar *) xmlRealloc(cur, (size + len + 1) * sizeof(xmlChar)); + ret = (xmlChar *) xmlRealloc(cur, (size_t) size + len + 1); if (ret == NULL) { - xmlErrMemory(NULL, NULL); - return(cur); + xmlFree(cur); + return(NULL); } +#ifdef MAGMA_ENABLE_CANARIES + // whenever size < 0, the previous reallocation results in allocating a @@ -21,10 +21,10 @@ index 8d2e06f..5715bb0 100644 + // elements into it, which will cause a heap buffer overflow. + MAGMA_LOG("%MAGMA_BUG%", size < 0); +#endif - memcpy(&ret[size], add, len * sizeof(xmlChar)); + memcpy(&ret[size], add, len); ret[size + len] = 0; return(ret); -@@ -488,8 +496,10 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { +@@ -496,8 +504,10 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { if (len < 0) { len = xmlStrlen(str2); @@ -33,25 +33,23 @@ index 8d2e06f..5715bb0 100644 return(NULL); +#endif } - if ((str2 == NULL) || (len == 0)) - return(xmlStrdup(str1)); -@@ -497,13 +507,19 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { + if (str1 == NULL) return(xmlStrndup(str2, len)); +@@ -505,11 +515,17 @@ xmlStrncatNew(const xmlChar *str1, const xmlChar *str2, int len) { + return(xmlStrdup(str1)); size = xmlStrlen(str1); +#ifdef MAGMA_ENABLE_FIXES - if (size < 0) + if ((size < 0) || (size > INT_MAX - len)) return(NULL); +#endif - ret = (xmlChar *) xmlMalloc((size + len + 1) * sizeof(xmlChar)); - if (ret == NULL) { - xmlErrMemory(NULL, NULL); - return(xmlStrndup(str1, size)); - } + ret = (xmlChar *) xmlMalloc((size_t) size + len + 1); + if (ret == NULL) + return(NULL); +#ifdef MAGMA_ENABLE_CANARIES + // ditto ;) + MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(size < 0, len < 0)); +#endif - memcpy(ret, str1, size * sizeof(xmlChar)); - memcpy(&ret[size], str2, len * sizeof(xmlChar)); + memcpy(ret, str1, size); + memcpy(&ret[size], str2, len); ret[size + len] = 0; diff --git a/targets/libxml2/patches/bugs/XML012.patch b/targets/libxml2/patches/bugs/XML012.patch new file mode 100644 index 000000000..9e1c642f6 --- /dev/null +++ b/targets/libxml2/patches/bugs/XML012.patch @@ -0,0 +1,42 @@ +diff --git a/parser.c b/parser.c +index ad035f3c..4a438f4b 100644 +--- a/parser.c ++++ b/parser.c +@@ -3520,6 +3520,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + XML_MAX_TEXT_LENGTH : + XML_MAX_NAME_LENGTH; + size_t startPosition = 0; ++ const xmlChar *end; + + ret.name = NULL; + ret.hashValue = 0; +@@ -3528,6 +3529,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + * Handler for more complex cases + */ + startPosition = CUR_PTR - BASE_PTR; ++ end = ctxt->input->cur; + c = xmlCurrentChar(ctxt, &l); + if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ + (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) { +@@ -3539,13 +3541,21 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { + if (len <= INT_MAX - l) + len += l; + NEXTL(l); ++ end = ctxt->input->cur; + c = xmlCurrentChar(ctxt, &l); + } + if (len > maxLength) { + xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); + return(ret); + } ++#ifdef MAGMA_ENABLE_FIXES + ret = xmlDictLookupHashed(ctxt->dict, (BASE_PTR + startPosition), len); ++#else ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (end - len) != (BASE_PTR + startPosition)); ++#endif ++ ret = xmlDictLookupHashed(ctxt->dict, (end - len), len); ++#endif + if (ret.name == NULL) + xmlErrMemory(ctxt); + return(ret); diff --git a/targets/libxml2/patches/bugs/XML015.patch b/targets/libxml2/patches/bugs/XML015.patch new file mode 100644 index 000000000..100cf2a1c --- /dev/null +++ b/targets/libxml2/patches/bugs/XML015.patch @@ -0,0 +1,39 @@ +# Codebase versions used for the following explaination: +# 1. Old code: htmlParseNameComplex() in HTMLparser.c (commit: ec6e3efb06d7b15cf5a2328fabd3845acea4c815) +# 2. New code: htmlParseData() in HTMLparser.c (commit: 41c10c0cec2ac072897c7d8df0e87fdf4b715586) + +# In the old code's name-parser, hitting a non-ASCII character could trigger an encoding switch +# and buffer reallocation. The if (base != old_base) + recursive call was the only place we ever +# restarted the ASCII fast-path, so disabling it re-introduced the "continue with stale pointers" bug. + +# In the new unified parser, that same "encoding switch -> must restart locals" logic is centralized +# in the goto restart;. Wrapping only the goto restart; under MAGMA_ENABLE_FIXES in theory shoul make +# the new parser behave just like the old fallback did: it sometimes fails to re-sync after a buffer move, +# leading us to scan off the end of a freed chunk. + +diff --git a/HTMLparser.c b/HTMLparser.c +index b9e176b3..cd4eace9 100644 +--- a/HTMLparser.c ++++ b/HTMLparser.c +@@ -2612,6 +2612,7 @@ static xmlChar * + htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask, + int comment, int refs, int maxLength) { + xmlParserInputPtr input = ctxt->input; ++ const xmlChar *bug_base = input->base; + xmlChar *ret = NULL; + xmlChar *buffer; + xmlChar utf8Char[4]; +@@ -2807,8 +2808,12 @@ htmlParseData(htmlParserCtxtPtr ctxt, htmlAsciiMask mask, + xmlFree(guess); + } + input->flags |= XML_INPUT_HAS_ENCODING; +- ++#ifdef MAGMA_ENABLE_FIXES + goto restart; ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", ctxt->input->base != bug_base); ++#endif + } + + size = htmlValidateUtf8(ctxt, in, avail); diff --git a/targets/libxml2/patches/failed/bugs/XML017.patch b/targets/libxml2/patches/bugs/XML017.patch similarity index 82% rename from targets/libxml2/patches/failed/bugs/XML017.patch rename to targets/libxml2/patches/bugs/XML017.patch index f17d70a73..2ced2fb08 100644 --- a/targets/libxml2/patches/failed/bugs/XML017.patch +++ b/targets/libxml2/patches/bugs/XML017.patch @@ -1,13 +1,13 @@ diff --git a/parser.c b/parser.c -index 3f31329..4aea5b8 100644 +index ad035f3c..7bbfaa7f 100644 --- a/parser.c +++ b/parser.c -@@ -8311,10 +8311,20 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) { +@@ -8385,10 +8385,20 @@ xmlParseInternalSubset(xmlParserCtxtPtr ctxt) { /* * We should be at the end of the DOCTYPE declaration. */ +#ifdef MAGMA_ENABLE_FIXES - if (RAW != '>') { + if ((ctxt->wellFormed) && (RAW != '>')) { xmlFatalErr(ctxt, XML_ERR_DOCTYPE_NOT_FINISHED, NULL); return; } diff --git a/targets/libxml2/patches/failed/bugs/XML007.patch b/targets/libxml2/patches/failed/bugs/XML007.patch deleted file mode 100644 index d8712965d..000000000 --- a/targets/libxml2/patches/failed/bugs/XML007.patch +++ /dev/null @@ -1,31 +0,0 @@ ---- a/HTMLparser.c -+++ b/HTMLparser.c -@@ -5392,6 +5392,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { - avail = in->length - (in->cur - in->base); - else - avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) - - (in->cur - in->base); -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", avail != (in->end - in->cur)); -+#endif - if ((avail == 0) && (terminate)) { - htmlAutoCloseOnEnd(ctxt); - if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) { ---- a/parser.c -+++ b/parser.c -@@ -12491,12 +12491,14 @@ xmlHaltParser(xmlParserCtxtPtr ctxt) { - ctxt->input->free((xmlChar *) ctxt->input->base); - ctxt->input->free = NULL; - } -+#ifdef MAGMA_ENABLE_FIXES - if (ctxt->input->buf != NULL) { - xmlFreeParserInputBuffer(ctxt->input->buf); - ctxt->input->buf = NULL; - } -- ctxt->input->cur = BAD_CAST""; - ctxt->input->length = 0; -+#endif -+ ctxt->input->cur = BAD_CAST""; - ctxt->input->base = ctxt->input->cur; - ctxt->input->end = ctxt->input->cur; - } diff --git a/targets/libxml2/patches/failed/bugs/XML012.patch b/targets/libxml2/patches/failed/bugs/XML012.patch deleted file mode 100644 index 12fd8b056..000000000 --- a/targets/libxml2/patches/failed/bugs/XML012.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/parser.c b/parser.c -index 3f31329..55b4bb4 100644 ---- a/parser.c -+++ b/parser.c -@@ -3349,6 +3349,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { - int c; - int count = 0; - size_t startPosition = 0; -+ const xmlChar *end; - - #ifdef DEBUG - nbParseNCNameComplex++; -@@ -3359,6 +3360,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { - */ - GROW; - startPosition = CUR_PTR - BASE_PTR; -+ end = ctxt->input->cur; - c = CUR_CHAR(l); - if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */ - (!xmlIsNameStartChar(ctxt, c) || (c == ':'))) { -@@ -3380,6 +3382,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { - } - len += l; - NEXTL(l); -+ end = ctxt->input->cur; - c = CUR_CHAR(l); - if (c == 0) { - count = 0; -@@ -3393,6 +3396,7 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { - if (ctxt->instate == XML_PARSER_EOF) - return(NULL); - ctxt->input->cur += l; -+ end = ctxt->input->cur; - c = CUR_CHAR(l); - } - } -@@ -3401,7 +3405,14 @@ xmlParseNCNameComplex(xmlParserCtxtPtr ctxt) { - xmlFatalErr(ctxt, XML_ERR_NAME_TOO_LONG, "NCName"); - return(NULL); - } -+#ifdef MAGMA_ENABLE_FIXES - return(xmlDictLookup(ctxt->dict, (BASE_PTR + startPosition), len)); -+#else -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (end - len) != (BASE_PTR + startPosition)); -+#endif -+ return(xmlDictLookup(ctxt->dict, (end - len), len)); -+#endif - } - - /** diff --git a/targets/libxml2/patches/failed/bugs/XML014.patch b/targets/libxml2/patches/failed/bugs/XML014.patch deleted file mode 100644 index 750b2bd4e..000000000 --- a/targets/libxml2/patches/failed/bugs/XML014.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/HTMLparser.c b/HTMLparser.c -index d6971b5..7c82c11 100644 ---- a/HTMLparser.c -+++ b/HTMLparser.c -@@ -2473,8 +2473,13 @@ htmlParseName(htmlParserCtxtPtr ctxt) { - (*in == ':') || (*in == '.')) - in++; - -+#ifdef MAGMA_ENABLE_FIXES - if (in == ctxt->input->end) - return(NULL); -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", in >= ctxt->input->end); -+#endif - - if ((*in > 0) && (*in < 0x80)) { - count = in - ctxt->input->cur; diff --git a/targets/libxml2/patches/failed/bugs/XML015.patch b/targets/libxml2/patches/failed/bugs/XML015.patch deleted file mode 100644 index 38009d194..000000000 --- a/targets/libxml2/patches/failed/bugs/XML015.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/HTMLparser.c b/HTMLparser.c -index d6971b5..15da2ae 100644 ---- a/HTMLparser.c -+++ b/HTMLparser.c -@@ -2519,6 +2519,7 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) { - len += l; - NEXTL(l); - c = CUR_CHAR(l); -+#ifdef MAGMA_ENABLE_FIXES - if (ctxt->input->base != base) { - /* - * We changed encoding from an unknown encoding -@@ -2526,6 +2527,10 @@ htmlParseNameComplex(xmlParserCtxtPtr ctxt) { - */ - return(htmlParseNameComplex(ctxt)); - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", ctxt->input->base != base); -+#endif - } - - if (ctxt->input->cur - ctxt->input->base < len) { diff --git a/targets/libxml2/patches/failed/bugs/XML002.patch b/targets/libxml2/patches/graveyard/XML002.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML002.patch rename to targets/libxml2/patches/graveyard/XML002.patch diff --git a/targets/libxml2/patches/failed/bugs/XML003.patch b/targets/libxml2/patches/graveyard/XML003.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML003.patch rename to targets/libxml2/patches/graveyard/XML003.patch diff --git a/targets/libxml2/patches/failed/bugs/XML005.patch b/targets/libxml2/patches/graveyard/XML005.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML005.patch rename to targets/libxml2/patches/graveyard/XML005.patch diff --git a/targets/libxml2/patches/graveyard/XML007.patch b/targets/libxml2/patches/graveyard/XML007.patch new file mode 100644 index 000000000..b930b4606 --- /dev/null +++ b/targets/libxml2/patches/graveyard/XML007.patch @@ -0,0 +1,52 @@ +# Codebase versions used for the following explaination: +# 1. Old code: htmlParseTryOrFinish() in HTMLparser.c, xmlHaltParser() in parser.c +# (commit: ec6e3efb06d7b15cf5a2328fabd3845acea4c815) +# 2. New code: htmlParseTryOrFinish() in HTMLparser.c, xmlHaltParser() in parserInternals.c +# (commit: 41c10c0cec2ac072897c7d8df0e87fdf4b715586) + +# In the earlier HTML parser, xmlHaltParser() itself freed the input stream. So removing that if in +# just this function was enough to introduce the dangling-pointer bug in exactly one place. + +# In the new parser: +# 1. All buffer freeing is moved into the generic destructor xmlFreeInputStream(), which is called +# when an input stream is popped or the parser context is torn down, not in haltParser. +# 2. xmlHaltParser() just sets instate=EOF and disableSAX and htmlParseTryOrFinish() never calls +# xmlFreeInputStream() directly. +# 3. Therefore, there is no code path where we can skip the free and introduce the bug in a specific way. +# We could skip the free in xmlFreeInputStream() but this will affect every parser and entity pop. +# Because buffer freeing happens in a shared teardown routine outside of the haltParser, we cannot +# reintroduce the old bug in a contained way. + +# Therefore it is not possible to re-introduce this bug due to complex structural changes. + +--- a/HTMLparser.c ++++ b/HTMLparser.c +@@ -5392,6 +5392,9 @@ htmlParseTryOrFinish(htmlParserCtxtPtr ctxt, int terminate) { + avail = in->length - (in->cur - in->base); + else + avail = (ptrdiff_t)xmlBufUse(in->buf->buffer) - + (in->cur - in->base); ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", avail != (in->end - in->cur)); ++#endif + if ((avail == 0) && (terminate)) { + htmlAutoCloseOnEnd(ctxt); + if ((ctxt->nameNr == 0) && (ctxt->instate != XML_PARSER_EOF)) { +--- a/parser.c ++++ b/parser.c +@@ -12491,12 +12491,14 @@ xmlHaltParser(xmlParserCtxtPtr ctxt) { + ctxt->input->free((xmlChar *) ctxt->input->base); + ctxt->input->free = NULL; + } ++#ifdef MAGMA_ENABLE_FIXES + if (ctxt->input->buf != NULL) { + xmlFreeParserInputBuffer(ctxt->input->buf); + ctxt->input->buf = NULL; + } +- ctxt->input->cur = BAD_CAST""; + ctxt->input->length = 0; ++#endif ++ ctxt->input->cur = BAD_CAST""; + ctxt->input->base = ctxt->input->cur; + ctxt->input->end = ctxt->input->cur; + } diff --git a/targets/libxml2/patches/failed/bugs/XML008.patch b/targets/libxml2/patches/graveyard/XML008.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML008.patch rename to targets/libxml2/patches/graveyard/XML008.patch diff --git a/targets/libxml2/patches/failed/bugs/XML009.patch b/targets/libxml2/patches/graveyard/XML009.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML009.patch rename to targets/libxml2/patches/graveyard/XML009.patch diff --git a/targets/libxml2/patches/failed/bugs/XML010.patch b/targets/libxml2/patches/graveyard/XML010.patch similarity index 100% rename from targets/libxml2/patches/failed/bugs/XML010.patch rename to targets/libxml2/patches/graveyard/XML010.patch diff --git a/targets/libxml2/patches/failed/bugs/XML013.patch b/targets/libxml2/patches/graveyard/XML013.patch similarity index 66% rename from targets/libxml2/patches/failed/bugs/XML013.patch rename to targets/libxml2/patches/graveyard/XML013.patch index e8bfd15fd..8328b757b 100644 --- a/targets/libxml2/patches/failed/bugs/XML013.patch +++ b/targets/libxml2/patches/graveyard/XML013.patch @@ -1,3 +1,21 @@ +# Codebase versions used for the following explaination: +# 1. Old code: htmlParseSystemLiteral() in HTMLparser.c (commit: ec6e3efb06d7b15cf5a2328fabd3845acea4c815) +# 2. New code: htmlParseDoctypeLiteral() in HTMLparser.c (commit: 41c10c0cec2ac072897c7d8df0e87fdf4b715586) + +# The new parser always passes everything through htmlParseData() which allocates its buffer, +# copies into it, and then returns a heap-allocated string. So we have no way to get at the raw +# input buffer start or length without re-introducing a bit of the old logic. To reproduce the +# old "copy straight from CUR_PTR" bug, we must: +# - Remember where in the input buffer you began (i.e. capture q = input->cur), +# - Let htmlParseData() run, +# - Discard its result and do our own xmlStrndup(q, input->cur - q). + +# Alternatives like trying to introduce that bug inside htmlParseData() would force us to re-implement +# the literal-scanning loop there (resurrecting all of the old byte-by-byte code), or require exposing +# internal buffers/pointers, which does not make sense with the unified function. + +# Therefore, it is not possible to re-introduce this bug without ressurecting old code. + diff --git a/HTMLparser.c b/HTMLparser.c index de624f8d..00b2fb1c 100644 --- a/HTMLparser.c diff --git a/targets/libxml2/patches/graveyard/XML014.patch b/targets/libxml2/patches/graveyard/XML014.patch new file mode 100644 index 000000000..1318be862 --- /dev/null +++ b/targets/libxml2/patches/graveyard/XML014.patch @@ -0,0 +1,39 @@ +# Codebase versions used for the following explaination: +# 1. Old code: htmlParseName() in HTMLparser.c (commit: ec6e3efb06d7b15cf5a2328fabd3845acea4c815) +# 2. New code: htmlParseData() in HTMLparser.c (commit: 41c10c0cec2ac072897c7d8df0e87fdf4b715586) + +# In the old code there was a two-phase "fast ASCII name" logic in htmlParseName which scanned forward +# over purely ASCII name characters up until either: +# a. It hit a non-name character (success), or +# b. It hit the very end of the in-memory buffer (in == end) (bail out, return NULL), +# and only if it bailed out did the parser refill the buffer and fall back to the slower, complex path. +# Because that fast path was a standalone function, re-introducing its exact "if you hit the buffer end, +# just return NULL” behavior could be done by dropping the if (in == end) return NULL; in htmlParseName. + +# In the new code there is no separate htmlParseName fast path. Every piece of HTML text is handled by +# the one big htmlParseData loop. Which never does a simple return NULL when it reaches input->end; +# instead it watches the avail = end - cur count and, before it ever risks running off the end, calls +# xmlParserGrow() to refill the buffer and then resumes scanning. Because name-character checking is just one +# branch inside a giant, mask-driven state machine, there is no isolated place where "we are in a name scan and +# we hit buffer end-return NULL" can be injected without turning the unified loop back into a two-phase design. + +# Therefore, it is not possible to re-introduce this bug without ressurecting old code. + +diff --git a/HTMLparser.c b/HTMLparser.c +index d6971b5..7c82c11 100644 +--- a/HTMLparser.c ++++ b/HTMLparser.c +@@ -2473,8 +2473,13 @@ htmlParseName(htmlParserCtxtPtr ctxt) { + (*in == ':') || (*in == '.')) + in++; + ++#ifdef MAGMA_ENABLE_FIXES + if (in == ctxt->input->end) + return(NULL); ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", in >= ctxt->input->end); ++#endif + + if ((*in > 0) && (*in < 0x80)) { + count = in - ctxt->input->cur; From 6b2d564889f0522df67bdf877dc2329054df6a3c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sun, 11 May 2025 23:49:33 +0200 Subject: [PATCH 078/150] Port bugs for libtiff --- targets/libtiff/patches/bugs/TIF002.patch | 22 ++++++++ targets/libtiff/patches/bugs/TIF003.patch | 20 ++++++++ targets/libtiff/patches/bugs/TIF004.patch | 35 +++++++++++++ targets/libtiff/patches/bugs/TIF005.patch | 24 +++++++++ .../patches/{failed => }/bugs/TIF007.patch | 24 ++++----- targets/libtiff/patches/bugs/TIF008.patch | 34 +++++++++++++ targets/libtiff/patches/bugs/TIF009.patch | 50 +++++++++++++++++++ targets/libtiff/patches/bugs/TIF011.patch | 24 +++++++++ targets/libtiff/patches/bugs/TIF012.patch | 47 +++++++++++++++++ targets/libtiff/patches/bugs/TIF013.patch | 27 ++++++++++ targets/libtiff/patches/bugs/TIF014.patch | 25 ++++++++++ .../libtiff/patches/failed/bugs/TIF002.patch | 22 -------- .../libtiff/patches/failed/bugs/TIF003.patch | 19 ------- .../libtiff/patches/failed/bugs/TIF004.patch | 25 ---------- .../libtiff/patches/failed/bugs/TIF005.patch | 24 --------- .../libtiff/patches/failed/bugs/TIF008.patch | 31 ------------ .../libtiff/patches/failed/bugs/TIF009.patch | 33 ------------ .../libtiff/patches/failed/bugs/TIF011.patch | 23 --------- .../libtiff/patches/failed/bugs/TIF012.patch | 45 ----------------- .../libtiff/patches/failed/bugs/TIF013.patch | 26 ---------- .../libtiff/patches/failed/bugs/TIF014.patch | 23 --------- 21 files changed, 320 insertions(+), 283 deletions(-) create mode 100644 targets/libtiff/patches/bugs/TIF002.patch create mode 100644 targets/libtiff/patches/bugs/TIF003.patch create mode 100644 targets/libtiff/patches/bugs/TIF004.patch create mode 100644 targets/libtiff/patches/bugs/TIF005.patch rename targets/libtiff/patches/{failed => }/bugs/TIF007.patch (62%) create mode 100644 targets/libtiff/patches/bugs/TIF008.patch create mode 100644 targets/libtiff/patches/bugs/TIF009.patch create mode 100644 targets/libtiff/patches/bugs/TIF011.patch create mode 100644 targets/libtiff/patches/bugs/TIF012.patch create mode 100644 targets/libtiff/patches/bugs/TIF013.patch create mode 100644 targets/libtiff/patches/bugs/TIF014.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF002.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF003.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF004.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF005.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF008.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF009.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF011.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF012.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF013.patch delete mode 100644 targets/libtiff/patches/failed/bugs/TIF014.patch diff --git a/targets/libtiff/patches/bugs/TIF002.patch b/targets/libtiff/patches/bugs/TIF002.patch new file mode 100644 index 000000000..14391ba83 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF002.patch @@ -0,0 +1,22 @@ +diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c +index 5ed921eb..06c38499 100644 +--- a/libtiff/tif_pixarlog.c ++++ b/libtiff/tif_pixarlog.c +@@ -881,12 +881,17 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) + TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size"); + return (0); + } ++#ifdef MAGMA_ENABLE_FIXES + /* Check that we will not fill more than what was allocated */ + if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) + { + TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size"); + return (0); + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (tmsize_t)sp->stream.avail_out > sp->tbuf_size); ++#endif + do + { + int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); diff --git a/targets/libtiff/patches/bugs/TIF003.patch b/targets/libtiff/patches/bugs/TIF003.patch new file mode 100644 index 000000000..d850c724e --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF003.patch @@ -0,0 +1,20 @@ +diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c +index 437c1a05..58c966d8 100644 +--- a/libtiff/tif_read.c ++++ b/libtiff/tif_read.c +@@ -495,8 +495,15 @@ static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF *tif, uint32_t strip, + rowsperstrip = td->td_rowsperstrip; + if (rowsperstrip > td->td_imagelength) + rowsperstrip = td->td_imagelength; ++#ifdef MAGMA_ENABLE_FIXES + stripsperplane = + TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); ++#else ++ stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip); ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", stripsperplane == 0); ++#endif + stripinplane = (strip % stripsperplane); + if (pplane) + *pplane = (uint16_t)(strip / stripsperplane); diff --git a/targets/libtiff/patches/bugs/TIF004.patch b/targets/libtiff/patches/bugs/TIF004.patch new file mode 100644 index 000000000..c420d33b7 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF004.patch @@ -0,0 +1,35 @@ +diff --git a/libtiff/tif_ojpeg.c b/libtiff/tif_ojpeg.c +index 57adcff8..513753f0 100644 +--- a/libtiff/tif_ojpeg.c ++++ b/libtiff/tif_ojpeg.c +@@ -862,12 +862,14 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) + static const char module[] = "OJPEGDecode"; + OJPEGState *sp = (OJPEGState *)tif->tif_data; + (void)s; ++#ifdef MAGMA_ENABLE_FIXES + if (!sp->decoder_ok) + { + TIFFErrorExtR(tif, module, + "Cannot decode: decoder not correctly initialized"); + return 0; + } ++#endif + if (sp->libjpeg_session_active == 0) + { + /* This should normally not happen, except that it does when */ +@@ -881,10 +883,15 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) + "Cannot decode: libjpeg_session_active == 0"); + return 0; + } ++#ifdef MAGMA_ENABLE_FIXES + if (sp->error_in_raw_data_decoding) + { + return 0; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", sp->decoder_ok == 0); ++#endif + if (sp->libjpeg_jpeg_query_style == 0) + { + if (OJPEGDecodeRaw(tif, buf, cc) == 0) diff --git a/targets/libtiff/patches/bugs/TIF005.patch b/targets/libtiff/patches/bugs/TIF005.patch new file mode 100644 index 000000000..6679b3d38 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF005.patch @@ -0,0 +1,24 @@ +diff --git a/libtiff/tif_luv.c b/libtiff/tif_luv.c +index 021756d5..6eb43723 100644 +--- a/libtiff/tif_luv.c ++++ b/libtiff/tif_luv.c +@@ -1663,7 +1663,9 @@ static void LogLuvClose(TIFF *tif) + * before they have been recorded in the file, we reset them here. + * Note: this is really a nasty approach. See PixarLogClose + */ ++#ifdef MAGMA_ENABLE_FIXES + if (sp->encoder_state) ++#endif + { + /* See PixarLogClose. Might avoid issues with tags whose size depends + * on those below, but not completely sure this is enough. */ +@@ -1672,6 +1674,9 @@ static void LogLuvClose(TIFF *tif) + td->td_bitspersample = 16; + td->td_sampleformat = SAMPLEFORMAT_INT; + } ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", sp->encoder_state == 0); ++#endif + } + + static void LogLuvCleanup(TIFF *tif) diff --git a/targets/libtiff/patches/failed/bugs/TIF007.patch b/targets/libtiff/patches/bugs/TIF007.patch similarity index 62% rename from targets/libtiff/patches/failed/bugs/TIF007.patch rename to targets/libtiff/patches/bugs/TIF007.patch index bab902d18..37f443a11 100644 --- a/targets/libtiff/patches/failed/bugs/TIF007.patch +++ b/targets/libtiff/patches/bugs/TIF007.patch @@ -1,8 +1,8 @@ diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c -index 1b300b0..b04612d 100644 +index cea569d5..f733bc07 100644 --- a/libtiff/tif_dirread.c +++ b/libtiff/tif_dirread.c -@@ -5773,7 +5773,11 @@ static void allocChoppedUpStripArrays(TIFF* tif, uint32 nstrips, +@@ -7373,7 +7373,11 @@ static void allocChoppedUpStripArrays(TIFF *tif, uint32_t nstrips, if (stripbytes > bytecount) stripbytes = bytecount; newcounts[i] = stripbytes; @@ -14,15 +14,14 @@ index 1b300b0..b04612d 100644 offset += stripbytes; bytecount -= stripbytes; } -@@ -5848,9 +5852,18 @@ ChopUpSingleUncompressedStrip(TIFF* tif) - */ - if (rowsperstrip >= td->td_rowsperstrip) - return; +@@ -7448,9 +7452,19 @@ static void ChopUpSingleUncompressedStrip(TIFF *tif) + */ + if (rowsperstrip >= td->td_rowsperstrip) + return; +#ifdef MAGMA_ENABLE_FIXES - nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); - if( nstrips == 0 ) - return; -- + nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); + if (nstrips == 0) + return; +#else + uint64_t nstrips64 = TIFFhowmany_64(bytecount, stripbytes); + if ((nstrips64==0)||(nstrips64>0xFFFFFFFF)) /* something is wonky, do nothing. */ @@ -32,5 +31,6 @@ index 1b300b0..b04612d 100644 +#ifdef MAGMA_ENABLE_CANARIES + MAGMA_LOG("%MAGMA_BUG%", nstrips > TIFFhowmany_32(td->td_imagelength, rowsperstrip)); +#endif - /* If we are going to allocate a lot of memory, make sure that the */ - /* file is as big as needed */ + + /* If we are going to allocate a lot of memory, make sure that the */ + /* file is as big as needed */ diff --git a/targets/libtiff/patches/bugs/TIF008.patch b/targets/libtiff/patches/bugs/TIF008.patch new file mode 100644 index 000000000..1e478804c --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF008.patch @@ -0,0 +1,34 @@ +diff --git a/libtiff/tif_next.c b/libtiff/tif_next.c +index f000574e..34cf0782 100644 +--- a/libtiff/tif_next.c ++++ b/libtiff/tif_next.c +@@ -137,11 +137,21 @@ static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) + * bounds, potentially resulting in a security + * issue. + */ ++#ifdef MAGMA_ENABLE_FIXES + while (n-- > 0 && npixels < imagewidth && + op_offset < scanline) ++#else ++ while (n-- > 0 && npixels < imagewidth) ++#endif ++ { ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", op_offset >= scanline); ++#endif + SETPIXEL(op, grey); ++ } + if (npixels >= imagewidth) + break; ++#ifdef MAGMA_ENABLE_FIXES + if (op_offset >= scanline) + { + TIFFErrorExtR(tif, module, +@@ -149,6 +159,7 @@ static int NeXTDecode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) + tif->tif_row); + return (0); + } ++#endif + if (cc == 0) + goto bad; + n = *bp++; diff --git a/targets/libtiff/patches/bugs/TIF009.patch b/targets/libtiff/patches/bugs/TIF009.patch new file mode 100644 index 000000000..2eb83a40a --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF009.patch @@ -0,0 +1,50 @@ +diff --git a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c +index d8844bbd..d91d134d 100644 +--- a/libtiff/tif_dirwrite.c ++++ b/libtiff/tif_dirwrite.c +@@ -2082,6 +2082,7 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, + /* clang-format on */ + + /* Check for proper number of transferfunctions */ ++#ifdef MAGMA_ENABLE_FIXES + for (int i = 0; i < n; i++) + { + if (tif->tif_dir.td_transferfunction[i] == NULL) +@@ -2092,6 +2093,29 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, + return (1); /* Not an error; only tag is not written. */ + } + } ++#else ++ if (n == 3) ++ { ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", tif->tif_dir.td_transferfunction[2] == NULL); ++#endif ++ if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], ++ tif->tif_dir.td_transferfunction[2], ++ m*sizeof(uint16_t))) ++ n=2; ++ } ++ if (n == 2) ++ { ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", tif->tif_dir.td_transferfunction[1] == NULL); ++#endif ++ if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0], ++ tif->tif_dir.td_transferfunction[1], ++ m*sizeof(uint16_t))) ++ n=1; ++ } ++#endif ++#ifdef MAGMA_ENABLE_FIXES + /* + * Check if the table can be written as a single column, + * or if it must be written as 3 columns. Note that we +@@ -2108,6 +2132,7 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, + m * sizeof(uint16_t))) + n = 1; + } ++#endif + o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t)); + if (o == NULL) + { diff --git a/targets/libtiff/patches/bugs/TIF011.patch b/targets/libtiff/patches/bugs/TIF011.patch new file mode 100644 index 000000000..ae751b772 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF011.patch @@ -0,0 +1,24 @@ +diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c +index 2b7fd176..3ceb7836 100644 +--- a/libtiff/tif_print.c ++++ b/libtiff/tif_print.c +@@ -584,10 +584,19 @@ void TIFFPrintDirectory(TIFF *tif, FILE *fd, long flags) + uint16_t i; + fprintf(fd, " %2ld: %5" PRIu16, l, + td->td_transferfunction[0][l]); ++#ifdef MAGMA_ENABLE_FIXES + for (i = 1; + i < td->td_samplesperpixel - td->td_extrasamples && i < 3; + i++) ++#else ++ for (i = 1; i < td->td_samplesperpixel; i++) ++#endif ++ { ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(i == sizeof(td->td_transferfunction) / sizeof(*td->td_transferfunction), i == (td->td_samplesperpixel - td->td_extrasamples))); ++#endif + fprintf(fd, " %5" PRIu16, td->td_transferfunction[i][l]); ++ } + fputc('\n', fd); + } + } diff --git a/targets/libtiff/patches/bugs/TIF012.patch b/targets/libtiff/patches/bugs/TIF012.patch new file mode 100644 index 000000000..dca83cbbe --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF012.patch @@ -0,0 +1,47 @@ +diff --git a/libtiff/tif_dir.c b/libtiff/tif_dir.c +index 47ad21e0..06689f24 100644 +--- a/libtiff/tif_dir.c ++++ b/libtiff/tif_dir.c +@@ -164,7 +164,7 @@ static int setExtraSamples(TIFF *tif, va_list ap, uint32_t *v) + return 0; + } + } +- ++#ifdef MAGMA_ENABLE_FIXES + if (td->td_transferfunction[0] != NULL && + (td->td_samplesperpixel - *v > 1) && + !(td->td_samplesperpixel - td->td_extrasamples > 1)) +@@ -177,6 +177,11 @@ static int setExtraSamples(TIFF *tif, va_list ap, uint32_t *v) + _TIFFfreeExt(tif, td->td_transferfunction[0]); + td->td_transferfunction[0] = NULL; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(td->td_transferfunction[0] != NULL, MAGMA_AND(td->td_samplesperpixel - *v > 1, \ ++ !(td->td_samplesperpixel - td->td_extrasamples > 1)))); ++#endif + + td->td_extrasamples = (uint16_t)*v; + _TIFFsetShortArrayExt(tif, &td->td_sampleinfo, va, td->td_extrasamples); +@@ -324,6 +329,7 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap) + goto badvalue; + if (v != td->td_samplesperpixel) + { ++#ifdef MAGMA_ENABLE_FIXES + /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */ + if (td->td_sminsamplevalue != NULL) + { +@@ -359,6 +365,13 @@ static int _TIFFVSetField(TIFF *tif, uint32_t tag, va_list ap) + TIFFClrFieldBit(tif, FIELD_TRANSFERFUNCTION); + _TIFFfreeExt(tif, td->td_transferfunction[0]); + td->td_transferfunction[0] = NULL; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(td->td_sminsamplevalue != NULL, \ ++ MAGMA_OR(td->td_smaxsamplevalue != NULL, \ ++ MAGMA_AND(td->td_transferfunction[0] != NULL, MAGMA_AND(v - td->td_extrasamples > 1, \ ++ !(td->td_samplesperpixel - td->td_extrasamples > 1)))))); ++#endif + } + td->td_samplesperpixel = (uint16_t)v; diff --git a/targets/libtiff/patches/bugs/TIF013.patch b/targets/libtiff/patches/bugs/TIF013.patch new file mode 100644 index 000000000..e4f9a13e5 --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF013.patch @@ -0,0 +1,27 @@ +diff --git a/libtiff/tif_jbig.c b/libtiff/tif_jbig.c +index 7e455ad1..78d4c384 100644 +--- a/libtiff/tif_jbig.c ++++ b/libtiff/tif_jbig.c +@@ -106,13 +106,22 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s) + } + else if ((tmsize_t)decodedSize > size) + { ++#ifdef MAGMA_ENABLE_FIXES + TIFFErrorExtR(tif, "JBIG", + "Decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT + " were requested", + decodedSize, size); + jbg_dec_free(&decoder); + return 0; ++#else ++ TIFFWarningExt(tif->tif_clientdata, "JBIG", ++ "Decoded %lu bytes, whereas %lu were requested", ++ decodedSize, (unsigned long)size); ++#endif + } ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", (tmsize_t)decodedSize > size); ++#endif + pImage = jbg_dec_getimage(&decoder, 0); + _TIFFmemcpy(buffer, pImage, decodedSize); + jbg_dec_free(&decoder); diff --git a/targets/libtiff/patches/bugs/TIF014.patch b/targets/libtiff/patches/bugs/TIF014.patch new file mode 100644 index 000000000..3b009802a --- /dev/null +++ b/targets/libtiff/patches/bugs/TIF014.patch @@ -0,0 +1,25 @@ +diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c +index cea569d5..0c973c32 100644 +--- a/libtiff/tif_dirread.c ++++ b/libtiff/tif_dirread.c +@@ -7454,12 +7454,20 @@ static void ChopUpSingleUncompressedStrip(TIFF *tif) + + /* If we are going to allocate a lot of memory, make sure that the */ + /* file is as big as needed */ ++#ifdef MAGMA_ENABLE_FIXES + if (tif->tif_mode == O_RDONLY && nstrips > 1000000 && + (offset >= TIFFGetFileSize(tif) || + stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1))) + { + return; + } ++#endif ++#ifdef MAGMA_ENABLE_CANARIES ++ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(tif->tif_mode == O_RDONLY, \ ++ MAGMA_AND(nstrips > 1000000, \ ++ MAGMA_OR(offset >= TIFFGetFileSize(tif), \ ++ stripbytes * (nstrips - 1) > (TIFFGetFileSize(tif) - offset))))); ++#endif + + allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip); + } diff --git a/targets/libtiff/patches/failed/bugs/TIF002.patch b/targets/libtiff/patches/failed/bugs/TIF002.patch deleted file mode 100644 index 444e1ddc4..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF002.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/libtiff/tif_pixarlog.c b/libtiff/tif_pixarlog.c -index b1e48d9..5901551 100644 ---- a/libtiff/tif_pixarlog.c -+++ b/libtiff/tif_pixarlog.c -@@ -804,12 +804,17 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } -+#ifdef MAGMA_ENABLE_FIXES - /* Check that we will not fill more than what was allocated */ - if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) - { - TIFFErrorExt(tif->tif_clientdata, module, "sp->stream.avail_out > sp->tbuf_size"); - return (0); - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (tmsize_t)sp->stream.avail_out > sp->tbuf_size); -+#endif - do { - int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); - if (state == Z_STREAM_END) { diff --git a/targets/libtiff/patches/failed/bugs/TIF003.patch b/targets/libtiff/patches/failed/bugs/TIF003.patch deleted file mode 100644 index 43e4eefd5..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF003.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff --git a/libtiff/tif_read.c b/libtiff/tif_read.c -index 1f5362a..0e8a1c6 100644 ---- a/libtiff/tif_read.c -+++ b/libtiff/tif_read.c -@@ -492,7 +492,14 @@ static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF* tif, uint32 strip, uint16 - rowsperstrip=td->td_rowsperstrip; - if (rowsperstrip>td->td_imagelength) - rowsperstrip=td->td_imagelength; -+#ifdef MAGMA_ENABLE_FIXES - stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); -+#else -+ stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip); -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", stripsperplane == 0); -+#endif - stripinplane=(strip%stripsperplane); - if( pplane ) *pplane=(uint16)(strip/stripsperplane); - rows=td->td_imagelength-stripinplane*rowsperstrip; diff --git a/targets/libtiff/patches/failed/bugs/TIF004.patch b/targets/libtiff/patches/failed/bugs/TIF004.patch deleted file mode 100644 index ed7c1355c..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF004.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/libtiff/tif_ojpeg.c b/libtiff/tif_ojpeg.c -index ad3e1e7..5abc4a9 100644 ---- a/libtiff/tif_ojpeg.c -+++ b/libtiff/tif_ojpeg.c -@@ -789,15 +789,20 @@ OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) - static const char module[]="OJPEGDecode"; - OJPEGState* sp=(OJPEGState*)tif->tif_data; - (void)s; -+#ifdef MAGMA_ENABLE_FIXES - if( !sp->decoder_ok ) - { - TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); - return 0; - } - if( sp->error_in_raw_data_decoding ) - { - return 0; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", sp->decoder_ok == 0); -+#endif - if (sp->libjpeg_jpeg_query_style==0) - { - if (OJPEGDecodeRaw(tif,buf,cc)==0) diff --git a/targets/libtiff/patches/failed/bugs/TIF005.patch b/targets/libtiff/patches/failed/bugs/TIF005.patch deleted file mode 100644 index a65840568..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF005.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff --git a/libtiff/tif_luv.c b/libtiff/tif_luv.c -index 6a63ead..780107e 100644 ---- a/libtiff/tif_luv.c -+++ b/libtiff/tif_luv.c -@@ -1587,7 +1587,9 @@ LogLuvClose(TIFF* tif) - * before they have been recorded in the file, we reset them here. - * Note: this is really a nasty approach. See PixarLogClose - */ -+#ifdef MAGMA_ENABLE_FIXES - if( sp->encoder_state ) -+#endif - { - /* See PixarLogClose. Might avoid issues with tags whose size depends - * on those below, but not completely sure this is enough. */ -@@ -1596,6 +1598,9 @@ LogLuvClose(TIFF* tif) - td->td_bitspersample = 16; - td->td_sampleformat = SAMPLEFORMAT_INT; - } -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", sp->encoder_state == 0); -+#endif - } - - static void diff --git a/targets/libtiff/patches/failed/bugs/TIF008.patch b/targets/libtiff/patches/failed/bugs/TIF008.patch deleted file mode 100644 index 9a0ca8ba1..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF008.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/libtiff/tif_next.c b/libtiff/tif_next.c -index 0ba61ae..ba8b3cc 100644 ---- a/libtiff/tif_next.c -+++ b/libtiff/tif_next.c -@@ -122,15 +122,26 @@ NeXTDecode(TIFF* tif, uint8* buf, tmsize_t occ, uint16 s) - * bounds, potentially resulting in a security - * issue. - */ -+#ifdef MAGMA_ENABLE_FIXES - while (n-- > 0 && npixels < imagewidth && op_offset < scanline) -+#else -+ while (n-- > 0 && npixels < imagewidth) -+#endif -+ { -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", op_offset >= scanline); -+#endif - SETPIXEL(op, grey); -+ } - if (npixels >= imagewidth) - break; -+#ifdef MAGMA_ENABLE_FIXES - if (op_offset >= scanline ) { - TIFFErrorExt(tif->tif_clientdata, module, "Invalid data for scanline %"PRIu32, - tif->tif_row); - return (0); - } -+#endif - if (cc == 0) - goto bad; - n = *bp++; diff --git a/targets/libtiff/patches/failed/bugs/TIF009.patch b/targets/libtiff/patches/failed/bugs/TIF009.patch deleted file mode 100644 index f7c0e31e1..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF009.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff --git a/libtiff/tif_dirwrite.c b/libtiff/tif_dirwrite.c -index 9e4d306..98d6e1a 100644 ---- a/libtiff/tif_dirwrite.c -+++ b/libtiff/tif_dirwrite.c -@@ -2026,14 +2026,28 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir - n=3; - if (n==3) - { -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", tif->tif_dir.td_transferfunction[2] == NULL); -+#endif -+#ifdef MAGMA_ENABLE_FIXES - if (tif->tif_dir.td_transferfunction[2] == NULL || - !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16_t))) -+#else -+ if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16_t))) -+#endif - n=2; - } - if (n==2) - { -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", tif->tif_dir.td_transferfunction[1] == NULL); -+#endif -+#ifdef MAGMA_ENABLE_FIXES - if (tif->tif_dir.td_transferfunction[1] == NULL || - !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16_t))) -+#else -+ if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16_t))) -+#endif - n=1; - } - if (n==0) diff --git a/targets/libtiff/patches/failed/bugs/TIF011.patch b/targets/libtiff/patches/failed/bugs/TIF011.patch deleted file mode 100644 index 963f10502..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF011.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/libtiff/tif_print.c b/libtiff/tif_print.c -index a073794..0a0e691 100644 ---- a/libtiff/tif_print.c -+++ b/libtiff/tif_print.c -@@ -544,9 +544,18 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) - uint16 i; - fprintf(fd, " %2ld: %5"PRIu16, - l, td->td_transferfunction[0][l]); -+#ifdef MAGMA_ENABLE_FIXES - for (i = 1; i < td->td_samplesperpixel - td->td_extrasamples && i < 3; i++) -+#else -+ for (i = 1; i < td->td_samplesperpixel; i++) -+#endif -+ { -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(i == sizeof(td->td_transferfunction) / sizeof(*td->td_transferfunction), i == (td->td_samplesperpixel - td->td_extrasamples))); -+#endif - fprintf(fd, " %5"PRIu16, - td->td_transferfunction[i][l]); -+ } - fputc('\n', fd); - } - } else diff --git a/targets/libtiff/patches/failed/bugs/TIF012.patch b/targets/libtiff/patches/failed/bugs/TIF012.patch deleted file mode 100644 index 0c3b807fb..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF012.patch +++ /dev/null @@ -1,45 +0,0 @@ ---- a/libtiff/tif_dir.c -+++ b/libtiff/tif_dir.c -@@ -117,7 +117,7 @@ setExtraSamples(TIFF* tif, va_list ap, uint32* v) - return 0; - } - } -- -+#ifdef MAGMA_ENABLE_FIXES - if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) && - !(td->td_samplesperpixel - td->td_extrasamples > 1)) - { -@@ -128,6 +128,11 @@ setExtraSamples(TIFF* tif, va_list ap, uint32* v) - _TIFFfree(td->td_transferfunction[0]); - td->td_transferfunction[0] = NULL; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(td->td_transferfunction[0] != NULL, MAGMA_AND(td->td_samplesperpixel - *v > 1, \ -+ !(td->td_samplesperpixel - td->td_extrasamples > 1)))); -+#endif - - td->td_extrasamples = (uint16) *v; - _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); -@@ -270,6 +275,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) - goto badvalue; - if( v != td->td_samplesperpixel ) - { -+#ifdef MAGMA_ENABLE_FIXES - /* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */ - if( td->td_sminsamplevalue != NULL ) - { -@@ -301,6 +307,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) - _TIFFfree(td->td_transferfunction[0]); - td->td_transferfunction[0] = NULL; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_OR(td->td_sminsamplevalue != NULL, \ -+ MAGMA_OR(td->td_smaxsamplevalue != NULL, \ -+ MAGMA_AND(td->td_transferfunction[0] != NULL, MAGMA_AND(v - td->td_extrasamples > 1, \ -+ !(td->td_samplesperpixel - td->td_extrasamples > 1)))))); -+#endif - } - td->td_samplesperpixel = (uint16) v; - break; diff --git a/targets/libtiff/patches/failed/bugs/TIF013.patch b/targets/libtiff/patches/failed/bugs/TIF013.patch deleted file mode 100644 index 19c575c1c..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF013.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/libtiff/tif_jbig.c b/libtiff/tif_jbig.c -index 7ffe885..a2bc7bf 100644 ---- a/libtiff/tif_jbig.c -+++ b/libtiff/tif_jbig.c -@@ -106,12 +106,21 @@ static int JBIGDecode(TIFF* tif, uint8* buffer, tmsize_t size, uint16 s) - } - else if( (tmsize_t)decodedSize > size ) - { -+#ifdef MAGMA_ENABLE_FIXES - TIFFErrorExt(tif->tif_clientdata, "JBIG", - "Decoded %lu bytes, whereas %"TIFF_SSIZE_FORMAT" were requested", - decodedSize, size); - jbg_dec_free(&decoder); - return 0; -+#else -+ TIFFWarningExt(tif->tif_clientdata, "JBIG", -+ "Decoded %lu bytes, whereas %lu were requested", -+ decodedSize, (unsigned long)size); -+#endif - } -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", (tmsize_t)decodedSize > size); -+#endif - pImage = jbg_dec_getimage(&decoder, 0); - _TIFFmemcpy(buffer, pImage, decodedSize); - jbg_dec_free(&decoder); diff --git a/targets/libtiff/patches/failed/bugs/TIF014.patch b/targets/libtiff/patches/failed/bugs/TIF014.patch deleted file mode 100644 index 5e84cbc57..000000000 --- a/targets/libtiff/patches/failed/bugs/TIF014.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/libtiff/tif_dirread.c b/libtiff/tif_dirread.c -index 1b300b0..47d6992 100644 ---- a/libtiff/tif_dirread.c -+++ b/libtiff/tif_dirread.c -@@ -5852,3 +5852,4 @@ ChopUpSingleUncompressedStrip(TIFF* tif) - /* If we are going to allocate a lot of memory, make sure that the */ - /* file is as big as needed */ -+#ifdef MAGMA_ENABLE_FIXES - if( tif->tif_mode == O_RDONLY && -@@ -5861,6 +5862,13 @@ ChopUpSingleUncompressedStrip(TIFF* tif) - { - return; - } -+#endif -+#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", MAGMA_AND(tif->tif_mode == O_RDONLY, \ -+ MAGMA_AND(nstrips > 1000000, \ -+ MAGMA_OR(offset >= TIFFGetFileSize(tif), \ -+ stripbytes * (nstrips - 1) > (TIFFGetFileSize(tif) - offset))))); -+#endif - - allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip); - } From cbb7929c7aa06cf415be115884c9c586e93db00e Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 21 May 2025 10:13:34 +0200 Subject: [PATCH 079/150] Fix canary in TIF003 --- targets/libtiff/patches/bugs/TIF003.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/libtiff/patches/bugs/TIF003.patch b/targets/libtiff/patches/bugs/TIF003.patch index d850c724e..a0a65837f 100644 --- a/targets/libtiff/patches/bugs/TIF003.patch +++ b/targets/libtiff/patches/bugs/TIF003.patch @@ -13,7 +13,7 @@ index 437c1a05..58c966d8 100644 + stripsperplane=((td->td_imagelength+rowsperstrip-1)/rowsperstrip); +#endif +#ifdef MAGMA_ENABLE_CANARIES -+ MAGMA_LOG("%MAGMA_BUG%", stripsperplane == 0); ++ MAGMA_LOG("%MAGMA_BUG%", rowsperstrip == 0); +#endif stripinplane = (strip % stripsperplane); if (pplane) From 6544b6eba6925ab0a67e83479cde68a25983df9e Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 12:40:56 +0200 Subject: [PATCH 080/150] Annotate magma_core build stage in Dockerfile --- docker/Dockerfile | 5 ++++- tools/captain/build.sh | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3b4ba505b..402c4b9ac 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,7 @@ -FROM ubuntu:24.04 +## +# Stage: build core magma +## +FROM ubuntu:24.04 AS magma_core # TODO remove sudo for user "magma" to avoid unwanted priv escalation from # other attack vectors. diff --git a/tools/captain/build.sh b/tools/captain/build.sh index afa9bb295..934b4b707 100755 --- a/tools/captain/build.sh +++ b/tools/captain/build.sh @@ -43,6 +43,7 @@ fi set -x docker build -t "$IMG_NAME" \ + --target magma_core \ --build-arg fuzzer_name="$FUZZER" \ --build-arg target_name="$TARGET" \ --build-arg target_version="$TARGET_VERSION" \ From 0369cbabbf1c470372088be3c92c73fa8d679664 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:19:17 +0200 Subject: [PATCH 081/150] Add scripts to spin up PoC run containers --- tools/captain/poc/build.sh | 30 ++++++++++ tools/captain/poc/run.sh | 117 +++++++++++++++++++++++++++++++++++++ tools/captain/poc/start.sh | 67 +++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100755 tools/captain/poc/build.sh create mode 100755 tools/captain/poc/run.sh create mode 100755 tools/captain/poc/start.sh diff --git a/tools/captain/poc/build.sh b/tools/captain/poc/build.sh new file mode 100755 index 000000000..21e5d18ef --- /dev/null +++ b/tools/captain/poc/build.sh @@ -0,0 +1,30 @@ +#!/bin/bash -e + +## +# Build a PoC image for a specific target and bug. +# Should only be called by tools/captain/poc/run.sh. +# Pre-requirements: +# - env POC_TARGET: PoC target name (from POC_TARGETS in captainrc) +# - env BUG: PoC bug name (from target_BUGS in tools/captain/poc_configs/target.conf) +## + +if [ -z $POC_TARGET ] || [ -z $BUG ]; then + echo '$POC_TARGET and $BUG must be specified as environment variables.' + exit 1 +fi + +IMG_NAME="magma/$POC_TARGET/${BUG,,}" +MAGMA=${MAGMA:-"$(cd "$(dirname "${BASH_SOURCE[0]}")/../../" >/dev/null 2>&1 && pwd)"} +source "$MAGMA/tools/captain/common.sh" + +set -x +docker build -t "$IMG_NAME" \ + --target magma_pocs \ + --build-arg poc_target_name="$POC_TARGET" \ + --build-arg poc_target_version="$TARGET_VERSION" \ + --build-arg poc_bug="$BUG" \ + --build-arg CRASH_PATH="$CRASH_INPUT" \ + -f "$MAGMA/docker/Dockerfile" "$MAGMA" +set +x + +echo "$IMG_NAME" diff --git a/tools/captain/poc/run.sh b/tools/captain/poc/run.sh new file mode 100755 index 000000000..1aa636d89 --- /dev/null +++ b/tools/captain/poc/run.sh @@ -0,0 +1,117 @@ +#!/bin/bash -e + +## +# Schedule the building and running of PoC images defined in POC_TARGETS +# [NOTE] This script depends on variabled from tools/captain/run.sh and +# should only be from by it. +# Pre-requirements: +# - env variables and exports from tools/captain/run.sh +## + +CRASH_INPUT="/test/crash_input" +CRASH_OUTPUT=/test/crash_output +CRASH_OUTPUT_NULL=/dev/null + +export POC_SUBDIR="poc" +export POC_LOGDIR="${LOGDIR}/${POC_SUBDIR}" +export POC_CACHEDIR="${CACHEDIR}/${POC_SUBDIR}" + +mkdir -p $POC_LOGDIR +mkdir -p $POC_CACHEDIR + +start_poc_run() +{ + launch_poc_run() + { + echo_time "Container $POC_TARGET/$BUG/$CACHECID started on CPU $AFFINITY" + if [ ! -z "$MAGMA_DEBUG" ]; then + "$MAGMA/tools/captain/$POC_SUBDIR/start.sh" + else + "$MAGMA/tools/captain/$POC_SUBDIR/start.sh" &> \ + "${POC_LOGDIR}/${POC_TARGET}_${BUG}_${CACHECID}_container.log" + fi + echo_time "Container $POC_TARGET/$BUG/$CACHECID stopped" + } + export -f launch_poc_run + + while : ; do + export POC_RUN_CACHEDIR="$POC_CACHEDIR/$POC_TARGET/$BUG" + export CACHECID=$(mutex $MUX_CID get_next_cid "$POC_RUN_CACHEDIR") + + errno_lock=69 + SHELL=/bin/bash flock -xnF -E $errno_lock "${POC_RUN_CACHEDIR}/${CACHECID}" \ + -c launch_poc_run || \ + if [ $? -eq $errno_lock ]; then + continue + fi + break + done +} +export -f start_poc_run + +start_ex_poc() +{ + release_workers() + { + IFS=',' + read -a workers <<< "$AFFINITY" + unset IFS + for i in "${workers[@]}"; do + rm -rf "$LOCKDIR/magma_cpu_$i" + done + } + trap release_workers EXIT + + start_poc_run + exit 0 +} +export -f start_ex_poc + + +if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first PoC target is chosen." + POC_TARGETS=(${POC_TARGETS[0]}) +fi + +# schedule PoC builds +for POC_TARGET in "${POC_TARGETS[@]}"; do + export POC_TARGET + source "$MAGMA/tools/captain/$POC_SUBDIR/configs/$POC_TARGET.conf" + + unset BUGS + BUGS=($(get_var_or_default $POC_TARGET 'BUGS')) + + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Only the first bug is chosen." + BUGS=(${BUGS[0]}) + fi + + for BUG in "${BUGS[@]}"; do + export BUG + + export BUG_COMMAND="$(get_var_or_default $BUG 'COMMAND')" + if [ -z "$BUG_COMMAND" ]; then + echo_time "No command defined for bug '$BUG', skipping." + continue + fi + + # build the Docker image + IMG_NAME="magma/$POC_TARGET/${BUG,,}" + echo_time "Building $IMG_NAME" + if ! "$MAGMA/tools/captain/$POC_SUBDIR/build.sh" &> \ + "${POC_LOGDIR}/${POC_TARGET}_${BUG}_build.log"; then + echo_time "Failed to build $IMG_NAME. Check build log for info." + continue + fi + + echo_time "Running PoCs for $POC_TARGET" + export NUMWORKERS="$(get_var_or_default $FUZZER 'CAMPAIGN_WORKERS')" + export AFFINITY=$(allocate_workers) + if [ ! -z "$MAGMA_DEBUG" ]; then + echo_time "Magma debug is enabled. Don't run start_ex_poc as a daemon." + start_ex_poc + else + start_ex_poc & + fi + done +done diff --git a/tools/captain/poc/start.sh b/tools/captain/poc/start.sh new file mode 100755 index 000000000..327ba329e --- /dev/null +++ b/tools/captain/poc/start.sh @@ -0,0 +1,67 @@ +#!/bin/bash -e + +## +# Start a PoC container for a specific target and bug. +# Should only be called by tools/captain/poc/run.sh. +# Pre-requirements: +# - env POC_TARGET: target name (from targets/) +# - env BUG: name of the bug to reproduce (e.g. TIF009) +# - env BUG_COMMAND: the command to run in the container to reproduce the bug +# - env AFFINITY: the CPU to bind the container to (default: no affinity) +## + +cleanup() { + if [ ! -t 1 ]; then + docker rm -f $container_id &> /dev/null + fi + exit 0 +} + +trap cleanup EXIT SIGINT SIGTERM + +if [ -z "$POC_TARGET" ] || [ -z "$BUG" ] || [ -z "$BUG_COMMAND" ]; then + echo '$POC_TARGET, $BUG, and $BUG_COMMAND must be specified as' \ + 'environment variables.' + exit 1 +fi + +MAGMA=${MAGMA:-"$(cd "$(dirname "${BASH_SOURCE[0]}")/../../" >/dev/null 2>&1 \ + && pwd)"} +export MAGMA +source "$MAGMA/tools/captain/common.sh" + +IMG_NAME="magma/$POC_TARGET/${BUG,,}" +RUN_COMMAND="$BUG_COMMAND; rc=\$?; echo \"[CONTAINER EXIT CODE] \$rc\"; exit \$rc" + +if [ ! -z $AFFINITY ]; then + flag_aff="--cpuset-cpus=$AFFINITY --env=AFFINITY=$AFFINITY" +fi + +if [ ! -z "$MAGMA_DEBUG" ]; then + flag_volume+=" --volume=$MAGMA/magma:/magma/magma" + flag_volume+=" --volume=$MAGMA/targets/$POC_TARGET:/magma/targets/$POC_TARGET/workdir" +fi + +if [ -t 1 ]; then + docker run -it --rm $flag_volume $flag_aff \ + --env=POC_TARGET=$POC_TARGET \ + --env=BUG=$BUG \ + --entrypoint=/bin/bash \ + "$IMG_NAME" +else + container_id=$( + docker run -dt $flag_volume $flag_aff \ + --env=POC_TARGET=$POC_TARGET \ + --env=BUG=$BUG \ + --network=none \ + --entrypoint=sh \ + "$IMG_NAME" \ + -c "$RUN_COMMAND" + ) + container_id=$(cut -c-12 <<< $container_id) + echo_time "Container for $POC_TARGET/$BUG started in $container_id" + docker logs -f "$container_id" & + exit_code=$(docker wait $container_id) + exit $exit_code +fi + From 21d1dd41b9fae9f9e0696f0a415f0effdb65a713 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:24:33 +0200 Subject: [PATCH 082/150] Call PoC run.sh from main run.sh if POC_MODE=1 --- tools/captain/captainrc | 11 +++++++++++ tools/captain/run.sh | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/tools/captain/captainrc b/tools/captain/captainrc index ee264adba..1b5acfda4 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -97,3 +97,14 @@ FUZZERS=(afl aflfast moptafl aflplusplus fairfuzz honggfuzz) # [TARGET_VERSION]: target version to be chosen from its releases file TARGET_VERSION=PIONEER + +# [POC_MODE]: wether or not to build PoCs for the targets specified in POC_TARGETS +# This mode will not run fuzzing campaigns, but it will build targets and generate +# the specified bug PoCs using crash files provided in the target folders. +# (default: 0) +# POC_MODE=1 + +# [POC_TARGETS]: for which targets the PoCs should be built. Specific bug configs +# can be provided in the pocs/.poc file +# (default: no targets) +# POC_TARGETS=(libpng libtiff) diff --git a/tools/captain/run.sh b/tools/captain/run.sh index 288998063..6a135358e 100755 --- a/tools/captain/run.sh +++ b/tools/captain/run.sh @@ -243,6 +243,13 @@ cleanup() trap cleanup EXIT +# If PoC mode is enabled, only build PoCs for specified targets +if [ "$POC_MODE" = "1" ]; then + cd "$MAGMA/tools/captain/poc" && \ + . ./run.sh + exit 0 +fi + if [ ! -z "$MAGMA_DEBUG" ]; then echo_time "Magma debug is enabled. Only the first fuzzer is chosen." FUZZERS=(${FUZZERS[0]}) From f6c59d57a63490af0ce4e9fe1589fcfbc2ae82c3 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:27:24 +0200 Subject: [PATCH 083/150] Exit on empty POC_TARGETS --- tools/captain/poc/run.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/captain/poc/run.sh b/tools/captain/poc/run.sh index 1aa636d89..cb5709437 100755 --- a/tools/captain/poc/run.sh +++ b/tools/captain/poc/run.sh @@ -8,6 +8,11 @@ # - env variables and exports from tools/captain/run.sh ## +if [[ -z "${POC_TARGETS}" ]]; then + echo_time "POC_TARGETS is not set or empty. Nothing to do." + exit 0 +fi + CRASH_INPUT="/test/crash_input" CRASH_OUTPUT=/test/crash_output CRASH_OUTPUT_NULL=/dev/null From 5fef6ecdeb47acfb82bf67fd49d76cf778c8194c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:28:10 +0200 Subject: [PATCH 084/150] Update apply_patches to allow applying one patch only --- magma/apply_patches.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/magma/apply_patches.sh b/magma/apply_patches.sh index 38989b114..e55c26e2b 100755 --- a/magma/apply_patches.sh +++ b/magma/apply_patches.sh @@ -6,8 +6,10 @@ set -e # - env TARGET: path to target work dir ## +BUGS_PATH="${1:-"$TARGET/patches/bugs"}" + # TODO filter patches by target config.yaml -find "$TARGET/patches/setup" "$TARGET/patches/bugs" -name "*.patch" | \ +find "$TARGET/patches/setup" $BUGS_PATH -name "*.patch" | \ while read patch; do echo "Applying $patch" name=${patch##*/} From e271f05fac8cb75005f8abfaeef29db73bb449b9 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:32:06 +0200 Subject: [PATCH 085/150] Comtinue on empty bugs --- tools/captain/poc/run.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/captain/poc/run.sh b/tools/captain/poc/run.sh index cb5709437..54f19386a 100755 --- a/tools/captain/poc/run.sh +++ b/tools/captain/poc/run.sh @@ -91,6 +91,11 @@ for POC_TARGET in "${POC_TARGETS[@]}"; do BUGS=(${BUGS[0]}) fi + if [[ -z "${BUGS}" ]]; then + echo_time "BUGS for $POC_TARGET is not set or empty. Nothing to do." + continue + fi + for BUG in "${BUGS[@]}"; do export BUG From beb7d733bb1df34757ba8e466178fd20e315622c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:32:48 +0200 Subject: [PATCH 086/150] Add the build PoC stage in Dockerfile --- docker/Dockerfile | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/docker/Dockerfile b/docker/Dockerfile index 402c4b9ac..3c65d1ff6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -94,3 +94,62 @@ ENV LDFLAGS="-L${OUT} -g" RUN ${FUZZER}/instrument.sh ENTRYPOINT ["/bin/bash", "-c", "${MAGMA}/run.sh"] + + +## +# Stage: build magma PoCs +## +FROM ubuntu:24.04 AS magma_pocs + +RUN apt-get update && apt-get install -y sudo g++ + +ARG magma_root=./ +ARG poc_target_name +ARG poc_target_version +ARG poc_bug +ENV MAGMA_R=/magma +ENV OUT=/magma_out +ENV CC=/usr/bin/gcc +ENV CXX=/usr/bin/g++ + +# set up user and group +ARG USER_ID=1001 +ARG GROUP_ID=1001 + +RUN mkdir -p /home && \ + groupadd -g ${GROUP_ID} magma && \ + useradd -l -u ${USER_ID} -K UMASK=0000 -d /home -g magma magma && \ + chown magma:magma /home +RUN echo "magma:amgam" | chpasswd && usermod -a -G sudo magma +RUN echo "magma ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers + +RUN mkdir -p ${OUT} && chown magma:magma ${OUT} && chmod 744 ${OUT} + +# copy over magma source code +ARG magma_path=magma +ENV MAGMA=${MAGMA_R}/${magma_path} + +USER root:root +RUN mkdir -p ${MAGMA} && chown magma:magma ${MAGMA} +COPY --chown=magma:magma ${magma_root}/${magma_path} ${MAGMA}/ + +# build a clean install of the target with a specific bug +ARG target_path=targets/${poc_target_name} +ENV TARGET_NAME=${poc_target_name} +ENV TARGET=${MAGMA_R}/${target_path} +ENV TARGET_VERSION=${poc_target_version} +ENV BUG_PATH=${TARGET}/patches/bugs/${poc_bug}.patch + +USER root:root +RUN mkdir -p ${TARGET} && chown magma:magma ${TARGET} +COPY --chown=magma:magma ${magma_root}/${target_path} ${TARGET}/ +RUN ${TARGET}/preinstall.sh +RUN ${MAGMA}/fetch_target.sh +RUN ${MAGMA}/apply_patches.sh ${BUG_PATH} +RUN ${TARGET}/build_poc.sh + +# copy over the PoC input +ARG CRASH_CONTAINER_PATH=/test/crash_input +ARG CRASH_INPUT_PATH=${magma_root}/${target_path}/pocs/${poc_bug}.crash + +COPY --chown=magma:magma ${CRASH_INPUT_PATH} ${CRASH_CONTAINER_PATH} From 27dab04216ca08f0b8e1a587adbf01959215eb48 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:33:44 +0200 Subject: [PATCH 087/150] Add PoC config for libtiff --- tools/captain/poc/configs/libtiff.conf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tools/captain/poc/configs/libtiff.conf diff --git a/tools/captain/poc/configs/libtiff.conf b/tools/captain/poc/configs/libtiff.conf new file mode 100644 index 000000000..2b2d4049c --- /dev/null +++ b/tools/captain/poc/configs/libtiff.conf @@ -0,0 +1,18 @@ +### +# Configuration parameters for libtiff PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which libtiff bugs to build PoCs for. default: None +## +libtiff_BUGS=(TIF007 TIF009) + +## +# Commands to reproduce PoC for each specified bug +## +TIF007_COMMAND="tiffinfo -D ${CRASH_INPUT} ${CRASH_OUTPUT}" +TIF009_COMMAND="tiffcp ${CRASH_INPUT} ${CRASH_OUTPUT}" From a1765cc1cff6139392614f970c789567e1ddadce Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:34:14 +0200 Subject: [PATCH 088/150] Add build_poc script and crash inputs for libtiff --- targets/libtiff/build_poc.sh | 22 ++++++++++++++++++++++ targets/libtiff/pocs/TIF007.crash | Bin 0 -> 6849 bytes targets/libtiff/pocs/TIF009.crash | Bin 0 -> 352 bytes 3 files changed, 22 insertions(+) create mode 100755 targets/libtiff/build_poc.sh create mode 100644 targets/libtiff/pocs/TIF007.crash create mode 100644 targets/libtiff/pocs/TIF009.crash diff --git a/targets/libtiff/build_poc.sh b/targets/libtiff/build_poc.sh new file mode 100755 index 000000000..9cb238a56 --- /dev/null +++ b/targets/libtiff/build_poc.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env OUT: path to directory where artifacts are stored +# - env CC, CXX, FLAGS, LIBS, etc... +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +./autogen.sh +./configure --disable-shared --enable-tools +make -j$(nproc) clean +make -j$(nproc) +make install diff --git a/targets/libtiff/pocs/TIF007.crash b/targets/libtiff/pocs/TIF007.crash new file mode 100644 index 0000000000000000000000000000000000000000..c9a2bc295117fb805506f8d02e04625c32e90d6c GIT binary patch literal 6849 zcmeGhdrVbz_&eNtxm@H%kca|v2h%`;ynvwMqD#7h;fvKwD-+ZaL#x%C542`;PI_$3 zM!D-_j}xP?&BbkxV81MbMAM3=lgxX z^ZmZ}kFv5XSO5TtZY6ny{pCfrGy8HcwSs~}bY1g1?Eo=^f=dCL7Ow!ae|G_QIS>=csk-y0!Kz*LlWWkw;>9#4A%)oh=O>$dyz0fiD5j6-X-|p zFs@H@2*eD5-gEdW1mrmW5_`czMbxif6Vul~ON$>lHZ=I_?oj_p&KtAoA>tb%V$=)s?JQ>v#f)f1vrup0`t zi}gvV9|}Ag@fd;I?3qHTTt{w)p;Sf4$EAsMj{#dOYF0@s6Xv<%>Ug9V1CaY8CzQo0+y4UMO8L%5z|xL$%-{ZphTpp|=H zox40=eHPN@;f&{KDhLBPh@&Bq4aAqvp~bA?gqcwiC?yZ3z{q4sh{FuB6_S^= zYgOlaiozp8MRqSiuO?%HMbOKEprAKbMmrsR!iTxH|pUWh>L|dB4QBO8@W;@>gWp76TYWG{64sf2?6nf^4ie7$&Hv0 ze&oy{ILntPS%ECiSc?_N(s8fY5ZQ_i-Gf#pfl(j_;RNhUn*9DIy&JPUOL$SVv+btc zOcHaId~?FH150>FD}4f33A2J&(?wEqxD&rJBv8?j`ooY`aI+!?kt2LNS$@UslHM7`b6_idw+iMWKR^m$rI5cG(EO>(KGRVuKPnDL6lahVuYY)Zh?-b!2Q9D2lRA%K(la?;RGCe5`Rp*%-=>q zqv~Y$Q_Yu)J~@`Q{NvcUs~n|^Y!jy|4;8`#DPUvq!C`|K2TOB)<$cKf&Zkc*g1qt3 zIeEjg^HoowI<7D+J3lESCw}B;=g{Gb)Ac6YhQ;6>LM?~`*D$4Fa|;4CuWUhB1o66Y zCyf@wsK!OY_K>+)X@SKObKPy7g6el{3aYy=Vl&l`x?3is;CzaboarZ^G$lAime@R@ z;-Ez%!3C=9QzMarYl2#R@$yjZ_{4% zX={AiI-j=E*E9Rvb-tA}nQ64RV?VFWjhn*MnMVGYFj-DAOx+?aZE#A^J>b1@HmDkuO zOjE`dkqHlpU+aMb=K@7vFa5dMo&Zz~_^6vaG%ZwXlqkXM(BtpXxt$p{wULVb6n>&JH8Blv{@E&CYVV4yPlZ&^Ta-VSa$6-NDvpl{(NGi*Zxqj)TXUBmSZGm;qyPoM7R7(G2 z6k=dtWM*Il+Mxi%jBqw10~3@Dk`slpfhrj#8JHP?6r)U8R*r6FWjTlq#0+W^Rl25A6-%BrfEob1x71l^MCq+|vbppXX;gJgj;BLe^i CfI6Z8 literal 0 HcmV?d00001 From 2d3127eacc5be2204ba95d16aacc776b265dacb2 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:43:47 +0200 Subject: [PATCH 089/150] Update build_poc.sh for poppler --- targets/libtiff/build_poc.sh | 3 +-- targets/poppler/build_poc.sh | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100755 targets/poppler/build_poc.sh diff --git a/targets/libtiff/build_poc.sh b/targets/libtiff/build_poc.sh index 9cb238a56..8006064d4 100755 --- a/targets/libtiff/build_poc.sh +++ b/targets/libtiff/build_poc.sh @@ -5,8 +5,7 @@ set -e # Globally installs the target in the image # Pre-requirements: # - env TARGET: path to target work dir -# - env OUT: path to directory where artifacts are stored -# - env CC, CXX, FLAGS, LIBS, etc... +# - env CC, CXX ## if [ ! -d "$TARGET/repo" ]; then diff --git a/targets/poppler/build_poc.sh b/targets/poppler/build_poc.sh new file mode 100755 index 000000000..b9e15083b --- /dev/null +++ b/targets/poppler/build_poc.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +cmake \ + -DBUILD_SHARED_LIBS=OFF \ + -DFONT_CONFIGURATION=generic \ + -DBUILD_GTK_TESTS=OFF \ + -DBUILD_QT5_TESTS=OFF \ + -DBUILD_CPP_TESTS=OFF \ + -DENABLE_LIBPNG=ON \ + -DENABLE_LIBTIFF=ON \ + -DENABLE_LIBJPEG=ON \ + -DENABLE_BOOST=ON \ + -DWITH_Cairo=ON \ + -DENABLE_UTILS=ON \ + -DENABLE_LIBCURL=OFF \ + -DENABLE_GLIB=OFF \ + -DENABLE_GOBJECT_INTROSPECTION=OFF \ + -DENABLE_QT5=OFF \ + -DENABLE_QT6=OFF \ + -DENABLE_NSS3=OFF \ + -DENABLE_GPGME=OFF + +make -j$(nproc) poppler poppler-cpp pdfimages pdftoppm +make install From 4f8d65230de377cf2d657e33bc2a1599ec5d0483 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 13:44:15 +0200 Subject: [PATCH 090/150] Add crashes and config for poppler --- targets/poppler/pocs/PDF018.crash | Bin 0 -> 93680 bytes tools/captain/poc/configs/poppler.conf | 17 +++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 targets/poppler/pocs/PDF018.crash create mode 100644 tools/captain/poc/configs/poppler.conf diff --git a/targets/poppler/pocs/PDF018.crash b/targets/poppler/pocs/PDF018.crash new file mode 100644 index 0000000000000000000000000000000000000000..1884b1b1e56bb8759a0733098142600fd2c3ddb5 GIT binary patch literal 93680 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

8v^Ieb9-y)gsyt-YY77QL{-&{;$OlOoHu<7#s z$oX8pBRDW8gg0P_RUBPWuvsT@#cSCpqLgJQi&Kq&4gD=5XF<_H zoT~G#LGDBp?$f4+ctu>5HoS&xA_@diiz8EvaZ4i*&q{nwaE~C-Zr=0Zw(pL?qaA5$ zJ-0OKdz?oO5AT<(UJ`j9;b=i!sd~4x|sc zqOn=-jWU;|vkEFbW4O+gOWqqrhXm1}A$r$BAtLwve!_c!ylA(=hYY>$^zR1|JvJI5 zFK%yJz6nd^{v1npNNaDc#Rj`{KLeE!3Oe^FDNK{ZU|E+5e9 zucCn<^7_OL`nM+GKf-5G(a%F~cd$k}6G~;7#Jknpp0(gn3n}2AnXG+OWMW!Iw-8Ym zmAvXKTx{SJ(wE3HH`n;*JhV8j`&&{E^=x;C5CFZCndwJ!)g|8PGHCkn>PoWddo#8%ipJwtL-UnuulV}jGiYFG)zjzGbC^7$CepjI$d2;#p8M~= zvS{>+J*U%;fD`NF+7m)Z_N13oR%nC19@i6|g%fNuwOb)Wn?x#TXl{5{(2@VE%t`Mf dQBVZR0|B!py)VkoCjuh9&&DRNp+I{7zW}eOOQ!$; literal 0 HcmV?d00001 diff --git a/tools/captain/poc/configs/poppler.conf b/tools/captain/poc/configs/poppler.conf new file mode 100644 index 000000000..77b3b7d1e --- /dev/null +++ b/tools/captain/poc/configs/poppler.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for poppler PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which poppler bugs to build PoCs for. default: None +## +poppler_BUGS=(PDF018) + +## +# Commands to reproduce PoC for each specified bug +## +PDF018_COMMAND="pdfimages ${CRASH_INPUT} ${CRASH_OUTPUT_NULL}" From dbbeec62690c1d3ebba93704b6bf9bd9031d1a90 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:02:05 +0200 Subject: [PATCH 091/150] Init PoC build for libpng --- targets/libpng/build_poc.sh | 21 +++++++++++++++++++++ targets/libpng/pocs/PNG001.crash | 2 ++ tools/captain/poc/configs/libpng.conf | 17 +++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100755 targets/libpng/build_poc.sh create mode 100644 targets/libpng/pocs/PNG001.crash create mode 100644 tools/captain/poc/configs/libpng.conf diff --git a/targets/libpng/build_poc.sh b/targets/libpng/build_poc.sh new file mode 100755 index 000000000..5222fe887 --- /dev/null +++ b/targets/libpng/build_poc.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +autoreconf -f -i +./configure --with-libpng-prefix=MAGMA_ --disable-shared +make -j$(nproc) clean +make -j$(nproc) libpng16.la +make install diff --git a/targets/libpng/pocs/PNG001.crash b/targets/libpng/pocs/PNG001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/libpng/pocs/PNG001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/libpng.conf b/tools/captain/poc/configs/libpng.conf new file mode 100644 index 000000000..1daa7d158 --- /dev/null +++ b/tools/captain/poc/configs/libpng.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for libtiff PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which libtiff bugs to build PoCs for. default: None +## +libpng_BUGS=(PNG001) + +## +# Commands to reproduce PoC for each specified bug +## +PNG001_COMMAND="libpng16-config --version" # TODO: replace with actual command From 46e7e3bd9e699e949fd05eb9c8a141437324331b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:10:12 +0200 Subject: [PATCH 092/150] Init PoC build for libsndfile --- targets/libsndfile/build_poc.sh | 21 +++++++++++++++++++++ targets/libsndfile/pocs/SND001.crash | 2 ++ tools/captain/poc/configs/libsndfile.conf | 17 +++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100755 targets/libsndfile/build_poc.sh create mode 100644 targets/libsndfile/pocs/SND001.crash create mode 100644 tools/captain/poc/configs/libsndfile.conf diff --git a/targets/libsndfile/build_poc.sh b/targets/libsndfile/build_poc.sh new file mode 100755 index 000000000..3f0c2b8d3 --- /dev/null +++ b/targets/libsndfile/build_poc.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +autoreconf -f -i +./configure --disable-shared +make -j$(nproc) clean +make -j$(nproc) +make install diff --git a/targets/libsndfile/pocs/SND001.crash b/targets/libsndfile/pocs/SND001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/libsndfile/pocs/SND001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/libsndfile.conf b/tools/captain/poc/configs/libsndfile.conf new file mode 100644 index 000000000..00323302b --- /dev/null +++ b/tools/captain/poc/configs/libsndfile.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for libtiff PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which libtiff bugs to build PoCs for. default: None +## +libsndfile_BUGS=(SND001) + +## +# Commands to reproduce PoC for each specified bug +## +SND001_COMMAND="pkg-config --modversion sndfile" # TODO: replace with actual command From c198fbfdf5e39208e3218a8b842cdbf78a129196 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:11:46 +0200 Subject: [PATCH 093/150] Init PoC build for libxml2 --- targets/libxml2/build_poc.sh | 25 +++++++++++++++++++++++++ targets/libxml2/pocs/XML001.crash | 2 ++ tools/captain/poc/configs/libxml2.conf | 17 +++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100755 targets/libxml2/build_poc.sh create mode 100644 targets/libxml2/pocs/XML001.crash create mode 100644 tools/captain/poc/configs/libxml2.conf diff --git a/targets/libxml2/build_poc.sh b/targets/libxml2/build_poc.sh new file mode 100755 index 000000000..ee88d49c0 --- /dev/null +++ b/targets/libxml2/build_poc.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +./autogen.sh \ + --with-http=no \ + --with-python=no \ + --with-lzma=yes \ + --with-threads=no \ + --disable-shared +make -j$(nproc) clean +make -j$(nproc) all +make install diff --git a/targets/libxml2/pocs/XML001.crash b/targets/libxml2/pocs/XML001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/libxml2/pocs/XML001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/libxml2.conf b/tools/captain/poc/configs/libxml2.conf new file mode 100644 index 000000000..e89a05757 --- /dev/null +++ b/tools/captain/poc/configs/libxml2.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for libtiff PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which libtiff bugs to build PoCs for. default: None +## +libxml2_BUGS=(XML001) + +## +# Commands to reproduce PoC for each specified bug +## +XML001_COMMAND="xml2-config --version" From e74f718380b8b539daf36a8bfd012ef87617064a Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:24:25 +0200 Subject: [PATCH 094/150] Init PoC build for lua --- targets/lua/build_poc.sh | 22 ++++++++++++++++++++++ targets/lua/pocs/LUA001.crash | 2 ++ tools/captain/poc/configs/lua.conf | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100755 targets/lua/build_poc.sh create mode 100644 targets/lua/pocs/LUA001.crash create mode 100644 tools/captain/poc/configs/lua.conf diff --git a/targets/lua/build_poc.sh b/targets/lua/build_poc.sh new file mode 100755 index 000000000..891bbb25a --- /dev/null +++ b/targets/lua/build_poc.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +make -j$(nproc) clean +make -j$(nproc) liblua.a +make -j$(nproc) lua + +mv liblua.a /usr/local/bin/ +mv lua /usr/local/bin/ diff --git a/targets/lua/pocs/LUA001.crash b/targets/lua/pocs/LUA001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/lua/pocs/LUA001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/lua.conf b/tools/captain/poc/configs/lua.conf new file mode 100644 index 000000000..069690c25 --- /dev/null +++ b/tools/captain/poc/configs/lua.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for poppler PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which poppler bugs to build PoCs for. default: None +## +lua_BUGS=(LUA001) + +## +# Commands to reproduce PoC for each specified bug +## +LUA001_COMMAND="lua -v" From 1125712cb3c6c2d3d1bb9ee4902b97eae027a031 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:33:15 +0200 Subject: [PATCH 095/150] Init PoC build for openssl --- targets/openssl/build_poc.sh | 26 ++++++++++++++++++++++++++ targets/openssl/pocs/SSL001.crash | 2 ++ tools/captain/poc/configs/openssl.conf | 17 +++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100755 targets/openssl/build_poc.sh create mode 100644 targets/openssl/pocs/SSL001.crash create mode 100644 tools/captain/poc/configs/openssl.conf diff --git a/targets/openssl/build_poc.sh b/targets/openssl/build_poc.sh new file mode 100755 index 000000000..48bd5c0b3 --- /dev/null +++ b/targets/openssl/build_poc.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" +cp "$TARGET/src/abilist.txt" "$TARGET/repo/abilist.txt" + +./config --debug disable-tests -DPEDANTIC \ + -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION no-shared no-module \ + enable-tls1_3 enable-rc5 enable-md2 enable-ec_nistp_64_gcc_128 enable-ssl3 \ + enable-ssl3-method enable-nextprotoneg enable-weak-ssl-ciphers \ + +make -j$(nproc) clean +make -j$(nproc) +make install diff --git a/targets/openssl/pocs/SSL001.crash b/targets/openssl/pocs/SSL001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/openssl/pocs/SSL001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/openssl.conf b/tools/captain/poc/configs/openssl.conf new file mode 100644 index 000000000..62ab2fce0 --- /dev/null +++ b/tools/captain/poc/configs/openssl.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for poppler PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which poppler bugs to build PoCs for. default: None +## +openssl_BUGS=(SSL001) + +## +# Commands to reproduce PoC for each specified bug +## +SSL001_COMMAND="openssl -v" From 8eaa024d9269a97e01cdd9c186cdcbf88fc3df29 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 15:47:55 +0200 Subject: [PATCH 096/150] Init PoC build for php --- targets/php/build_poc.sh | 53 ++++++++++++++++++++++++++++++ targets/php/pocs/PHP001.crash | 2 ++ tools/captain/poc/configs/php.conf | 17 ++++++++++ 3 files changed, 72 insertions(+) create mode 100755 targets/php/build_poc.sh create mode 100644 targets/php/pocs/PHP001.crash create mode 100644 tools/captain/poc/configs/php.conf diff --git a/targets/php/build_poc.sh b/targets/php/build_poc.sh new file mode 100755 index 000000000..5bb112c0a --- /dev/null +++ b/targets/php/build_poc.sh @@ -0,0 +1,53 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch_target.sh must be executed first." + exit 1 +fi + +cp -r "$TARGET/oniguruma" "$TARGET/repo/oniguruma" && \ + sudo rm -rf "$TARGET/oniguruma" + +cd "$TARGET/repo" + +export ONIG_CFLAGS="-I$PWD/oniguruma/src" +export ONIG_LIBS="-L$PWD/oniguruma/src/.libs -l:libonig.a" +export CFLAGS="-fPIE" +export CXXFLAGS="-fPIE" +export LDFLAGS="$LDFLAGS -pie" + +#build the php library +./buildconf + +./configure \ + --disable-all \ + --enable-option-checking=fatal \ + --enable-exif \ + --enable-phar \ + --enable-intl \ + --enable-mbstring \ + --without-pcre-jit \ + --disable-phpdbg \ + --disable-cgi \ + --with-pic \ + ac_cv_func_fork=yes + +make -j$(nproc) clean + +# build oniguruma and link statically +pushd oniguruma +autoreconf -vfi +./configure --disable-shared +make -j$(nproc) +popd + +make -j$(nproc) +make install diff --git a/targets/php/pocs/PHP001.crash b/targets/php/pocs/PHP001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/php/pocs/PHP001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/poc/configs/php.conf b/tools/captain/poc/configs/php.conf new file mode 100644 index 000000000..1f4a58918 --- /dev/null +++ b/tools/captain/poc/configs/php.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for poppler PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which poppler bugs to build PoCs for. default: None +## +php_BUGS=(PHP001) + +## +# Commands to reproduce PoC for each specified bug +## +PHP001_COMMAND="php -v" From 9e09a6b719ce1e1e88a0fe316c82cdb3cd301af2 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Sat, 24 May 2025 16:07:26 +0200 Subject: [PATCH 097/150] Init PoC build for sqlite3 --- docker/Dockerfile | 2 +- targets/sqlite3/build_poc.sh | 29 ++++++++++++++++++++++++++ targets/sqlite3/pocs/SQL001.crash | 2 ++ tools/captain/captainrc | 2 +- tools/captain/poc/configs/sqlite3.conf | 17 +++++++++++++++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100755 targets/sqlite3/build_poc.sh create mode 100644 targets/sqlite3/pocs/SQL001.crash create mode 100644 tools/captain/poc/configs/sqlite3.conf diff --git a/docker/Dockerfile b/docker/Dockerfile index 3c65d1ff6..a093e0efe 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -101,7 +101,7 @@ ENTRYPOINT ["/bin/bash", "-c", "${MAGMA}/run.sh"] ## FROM ubuntu:24.04 AS magma_pocs -RUN apt-get update && apt-get install -y sudo g++ +RUN apt-get update && apt-get install -y sudo g++ git ARG magma_root=./ ARG poc_target_name diff --git a/targets/sqlite3/build_poc.sh b/targets/sqlite3/build_poc.sh new file mode 100755 index 000000000..0df175b9a --- /dev/null +++ b/targets/sqlite3/build_poc.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +## +# Globally installs the target in the image +# Pre-requirements: +# - env TARGET: path to target work dir +# - env CC, CXX +## + +if [ ! -d "$TARGET/repo" ]; then + echo "fetch.sh must be executed first." + exit 1 +fi + +cd "$TARGET/repo" + +export CFLAGS="$CFLAGS -DSQLITE_MAX_LENGTH=128000000 \ + -DSQLITE_MAX_SQL_LENGTH=128000000 \ + -DSQLITE_MAX_MEMORY=25000000 \ + -DSQLITE_PRINTF_PRECISION_LIMIT=1048576 \ + -DSQLITE_DEBUG=1 \ + -DSQLITE_MAX_PAGE_COUNT=16384" + +./configure --disable-shared --enable-rtree +make clean +make -j$(nproc) +make sqlite3.c +make install diff --git a/targets/sqlite3/pocs/SQL001.crash b/targets/sqlite3/pocs/SQL001.crash new file mode 100644 index 000000000..9b6552674 --- /dev/null +++ b/targets/sqlite3/pocs/SQL001.crash @@ -0,0 +1,2 @@ +# TODO: Replace this with a real crash and investigate how to to cause this crash +# and add the corresponding bug command diff --git a/tools/captain/captainrc b/tools/captain/captainrc index 1b5acfda4..1ff9b1b1c 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -107,4 +107,4 @@ TARGET_VERSION=PIONEER # [POC_TARGETS]: for which targets the PoCs should be built. Specific bug configs # can be provided in the pocs/.poc file # (default: no targets) -# POC_TARGETS=(libpng libtiff) +# POC_TARGETS=(libpng libsndfile libtiff libxml2 lua openssl php poppler sqlite3) diff --git a/tools/captain/poc/configs/sqlite3.conf b/tools/captain/poc/configs/sqlite3.conf new file mode 100644 index 000000000..44848a96e --- /dev/null +++ b/tools/captain/poc/configs/sqlite3.conf @@ -0,0 +1,17 @@ +### +# Configuration parameters for poppler PoCs +# Variables available to use in bug commands: +# - env CRASH_INPUT: /test/crash_input (from run_pocs.sh) +# - env CRASH_OUTPUT: /test/crash_output (from run_pocs.sh) +# - env CRASH_OUTPUT_NULL: /dev/null (from run_pocs.sh) +### + +## +# Which poppler bugs to build PoCs for. default: None +## +sqlite3_BUGS=(SQL001) + +## +# Commands to reproduce PoC for each specified bug +## +SQL001_COMMAND="sqlite3 --version" From a032d5198f84ff15b1ab4e0693c9aac99d1f2868 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 27 May 2025 10:08:10 +0200 Subject: [PATCH 098/150] Add PoC for LUA002 --- targets/lua/pocs/LUA001.crash | 2 -- targets/lua/pocs/LUA002.crash | Bin 0 -> 17753 bytes tools/captain/poc/configs/lua.conf | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 targets/lua/pocs/LUA001.crash create mode 100644 targets/lua/pocs/LUA002.crash diff --git a/targets/lua/pocs/LUA001.crash b/targets/lua/pocs/LUA001.crash deleted file mode 100644 index 9b6552674..000000000 --- a/targets/lua/pocs/LUA001.crash +++ /dev/null @@ -1,2 +0,0 @@ -# TODO: Replace this with a real crash and investigate how to to cause this crash -# and add the corresponding bug command diff --git a/targets/lua/pocs/LUA002.crash b/targets/lua/pocs/LUA002.crash new file mode 100644 index 0000000000000000000000000000000000000000..29e1baef7d22d182abfeb522fac973f5604f8cae GIT binary patch literal 17753 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 Date: Tue, 27 May 2025 12:02:56 +0200 Subject: [PATCH 099/150] Add a Poc for SQL018 --- targets/sqlite3/pocs/SQL001.crash | 2 -- targets/sqlite3/pocs/SQL018.crash | 4 ++++ tools/captain/poc/configs/sqlite3.conf | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 targets/sqlite3/pocs/SQL001.crash create mode 100644 targets/sqlite3/pocs/SQL018.crash diff --git a/targets/sqlite3/pocs/SQL001.crash b/targets/sqlite3/pocs/SQL001.crash deleted file mode 100644 index 9b6552674..000000000 --- a/targets/sqlite3/pocs/SQL001.crash +++ /dev/null @@ -1,2 +0,0 @@ -# TODO: Replace this with a real crash and investigate how to to cause this crash -# and add the corresponding bug command diff --git a/targets/sqlite3/pocs/SQL018.crash b/targets/sqlite3/pocs/SQL018.crash new file mode 100644 index 000000000..32e3753ce --- /dev/null +++ b/targets/sqlite3/pocs/SQL018.crash @@ -0,0 +1,4 @@ +--i) AS ( + SELECT 0 EXCEPT SELECT 0 ORDER BY 1 COLLATE """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""��""""""""""""""hsql_tert 15.1 { + WITH RECURSIVE + c(x) AS (VALUES(1) diff --git a/tools/captain/poc/configs/sqlite3.conf b/tools/captain/poc/configs/sqlite3.conf index 44848a96e..c80fc69b9 100644 --- a/tools/captain/poc/configs/sqlite3.conf +++ b/tools/captain/poc/configs/sqlite3.conf @@ -9,9 +9,9 @@ ## # Which poppler bugs to build PoCs for. default: None ## -sqlite3_BUGS=(SQL001) +sqlite3_BUGS=(SQL018) ## # Commands to reproduce PoC for each specified bug ## -SQL001_COMMAND="sqlite3 --version" +SQL018_COMMAND="sqlite3 :memory: < ${CRASH_INPUT}" From d4d2d7a00cb87beb6212890284b1c97d8f089e6b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 27 May 2025 12:58:31 +0200 Subject: [PATCH 100/150] Update libpng build PoC --- targets/libpng/build_poc.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/libpng/build_poc.sh b/targets/libpng/build_poc.sh index 5222fe887..3f0c2b8d3 100755 --- a/targets/libpng/build_poc.sh +++ b/targets/libpng/build_poc.sh @@ -15,7 +15,7 @@ fi cd "$TARGET/repo" autoreconf -f -i -./configure --with-libpng-prefix=MAGMA_ --disable-shared +./configure --disable-shared make -j$(nproc) clean -make -j$(nproc) libpng16.la +make -j$(nproc) make install From d327ddf402f58db7299a7033ba47f1e7f00ba836 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 27 May 2025 16:59:18 +0200 Subject: [PATCH 101/150] Add PoC for SND001 --- targets/libsndfile/pocs/SND001.crash | Bin 122 -> 2409 bytes tools/captain/poc/configs/libsndfile.conf | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/libsndfile/pocs/SND001.crash b/targets/libsndfile/pocs/SND001.crash index 9b65526742fad32659a3faf738f3d48716394bb1..0459ec75922576ade23df08a933e81dc31fb5292 100644 GIT binary patch literal 2409 zcmb7EZBSEZ7LJy70ywkz62a-t;!NGG`o35l=_n1Fn!V+y69;Esd4Bq&rUFqJB!i+tDxI%ri&+3dxg=?~q`Y|oEp z&N=UMo^#H<@4U=o+Fa64w&zcTyJ0W#tM$x=b$H$4hVLJL_LazN0-0v3FMsFr>m6pZ z`E}ke&iqWjU##;w}6ElDue)^m{AUuT#o=Wv^oN76(S5Hh$rpG6^LEMt~-y#tSz?$e@!@ z;=k8G2N~U>vM((@{wL;-a<In>_1uS}xd2_7=p&ao8lv}es7|$(p2++&ZY^?$q{svV!3v$f$|x#gWfk#_JGbt0E$JrbspA_w5nlU;F8>^3%Jlh zjm&-0%_}}BPf&JZ-heB!wx?6s-l^>?)fArX z><rwMZQPK()14|B-vwQxi-7X z=L&baSRb&?UT1Ze^8kz^XPO&IM2>SZ#tb>!ff7imaIkKLj!hO)Bg8Z_AQJH z7n7#fFXX!E4oAnby?4-^dU?W*IW(B(?%i5pl7t(VQ&=|z^9)=8TQHb?WZG!3 zI9Z7;+$`bep5hpdTF^K$esyWIGia&6u(63)9&4@liE+N7*J%4G~>} z;+&kLoCR`|IIsj+D`8abE2b_C1m$ z9_sM5j0)?EW0Zsf*0XfC$WVa`8hu9I>IWCsUqT;OzAGf`K2+m%DE%#p%F_wGG4|BO|!LQT;!?Q0V7R zGv%jO6-V_xs51Tw&+4<<@fr^uQVZJuy1!|3)DHFkcY>5Pz9u6lz_DERq!w%0 zLHpU-JLlzmb>8O4#5Vb<^NP+uB4)t`0&|NnFBr(dE2);Iu2TL)RE1a|nbsBkz#B~T z;+V6kE_5&0h;tb=wN)jfS2O2EmkwUhSJK1Rzim~CQ0c`gSem(k#gi-8A+Oh!G+WAB zb`m14q}7m6A;xiTRA%?(ydeea#38>jvv+rNmn!t)=Ee<=kF8%MlKUkVzQnng$X`#B zjD6EKDj8v#ZJcY*hD#+3kYd_LrAb?AKhEdT5P*zQsf>=9$=mn5A{3w?0Hm7CpIO2c z5XA&gY@FV%a|IVF!o!FoP+T-K`LV}B)KJW*AmPW!;Z>2Daee1WCQ@E z3!mRFxL_lj2`0oYx;A<0dl00U0b+>vmv-Ji;S~{mO(<$t?CxEhvxJA4K#(TwS}mDr zL=k{W76}r*nW|kCnaxB*rL`8Zy^x}2}MzN(Mq!+ z14T`ih`6@qU5i#i9YJVsrFUM`=0RT$je!5L| zLxk)#S#LNxE2S_(5CD_od)2iDzy#bXe~X6TwCJ>OVC__4jW!&D${D_Ua`z?(G9?G8 zJMTS#2urSic<>P{62B1+AhlKhm<=}(JPE^>&%OmytmV4dh%wxsB6=|W@e#%b?J6?Rdb~!iq*igE+Hkd2Bbt_ej{3TUp-vMhC K>9g?PcKio{mYaqE literal 122 zcmXYpK?;B{3|GE)5ZllOw3R06_pL?P%PzAsV4bIV#KPxJo?%H8k5~es yGVSn{w3Qqn`DQhVWQ`H*}anXfB2?wX&Wi2gwoJ729$gP3K+@7%Hp) diff --git a/tools/captain/poc/configs/libsndfile.conf b/tools/captain/poc/configs/libsndfile.conf index 00323302b..61f5e395b 100644 --- a/tools/captain/poc/configs/libsndfile.conf +++ b/tools/captain/poc/configs/libsndfile.conf @@ -14,4 +14,4 @@ libsndfile_BUGS=(SND001) ## # Commands to reproduce PoC for each specified bug ## -SND001_COMMAND="pkg-config --modversion sndfile" # TODO: replace with actual command +SND001_COMMAND="sndfile-info ${CRASH_INPUT}" From c61612c76b2474ccbd4e67a18b0c7efd082271b9 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Wed, 28 May 2025 12:23:25 +0200 Subject: [PATCH 102/150] Add PoC for PHP011 --- targets/php/pocs/PHP001.crash | 2 -- targets/php/pocs/PHP011.crash | Bin 0 -> 4712 bytes tools/captain/poc/configs/php.conf | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 targets/php/pocs/PHP001.crash create mode 100644 targets/php/pocs/PHP011.crash diff --git a/targets/php/pocs/PHP001.crash b/targets/php/pocs/PHP001.crash deleted file mode 100644 index 9b6552674..000000000 --- a/targets/php/pocs/PHP001.crash +++ /dev/null @@ -1,2 +0,0 @@ -# TODO: Replace this with a real crash and investigate how to to cause this crash -# and add the corresponding bug command diff --git a/targets/php/pocs/PHP011.crash b/targets/php/pocs/PHP011.crash new file mode 100644 index 0000000000000000000000000000000000000000..d1f1472031e58bfda2a6c36fc055917b99e38698 GIT binary patch literal 4712 zcmcDqFUTn1Dk-W|sOCy6E>0~f(J)X@Q&Z4TNmQ^=NGr`tF3HT#Q_#=^$}0eYN?GE@ zA_ZFo^^(-$5_M~cSaAtRNC_xc#K1Ifc4ASqVXTfq4Fi5)00Szec`2!BnR&BPKqB}x zL1fbch*5=2&2tFACPg!``IMOapAyZ3Q?Gy@N$z5jBS|?`6!TKWl%Z#ck~Nn~vaVes zFgxd!=Hys&0kd>`N@;F^hORDHLerY7G_N?dL<7c4P0q+yP;$*JD5+EcmIIl2=`ndg zQy{_t{=p#%o_@|?A(+8RKxw$KU_otd9L9q6ySO?JXh4#fTnE&xBgS%2LLCL8Aut*O zqaiRF0{BB9ZdJG;lBm%!+o-&nrpIE7A2y z%}X!IFpLFC0UOe_n!xT?twM5QNpgmQh9h_s2sr5DT2z!@q@a=t8~Oov>C~ZvM4DC# u>OfOdb?wqqOMFv{ixbmRH8gb;)D_YaGjmc?fRX_o0r9T>K0u?n?Ck&pNOU;> literal 0 HcmV?d00001 diff --git a/tools/captain/poc/configs/php.conf b/tools/captain/poc/configs/php.conf index 1f4a58918..96ea2ccae 100644 --- a/tools/captain/poc/configs/php.conf +++ b/tools/captain/poc/configs/php.conf @@ -9,9 +9,9 @@ ## # Which poppler bugs to build PoCs for. default: None ## -php_BUGS=(PHP001) +php_BUGS=(PHP011) ## # Commands to reproduce PoC for each specified bug ## -PHP001_COMMAND="php -v" +PHP011_COMMAND="php -l ${CRASH_INPUT}" From 79cb4047d53f36bded57c75027955da7e0f85105 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Sun, 1 Jun 2025 09:19:44 +0200 Subject: [PATCH 103/150] Collect source-based code coverage - Add COV=/magma_cov - Instrument the target to collect source-based code coverage - Replay the corpus and dump the coverage metadata - Merge the coverage metadata and report coverage in html/json in $SHARED --- docker/Dockerfile | 11 +++++--- fuzzers/aflplusplus/build.sh | 2 +- fuzzers/aflplusplus/coverage.sh | 12 +++++++++ fuzzers/aflplusplus/instrument.sh | 13 ++++++++++ fuzzers/aflplusplus/preinstall.sh | 1 + fuzzers/aflplusplus/runonce.sh | 4 +++ fuzzers/honggfuzz/coverage.sh | 11 ++++++++ fuzzers/honggfuzz/instrument.sh | 15 ++++++++++- fuzzers/honggfuzz/preinstall.sh | 1 + fuzzers/honggfuzz/runonce.sh | 4 +++ fuzzers/libfuzzer/coverage.sh | 13 ++++++++++ fuzzers/libfuzzer/instrument.sh | 13 ++++++++++ fuzzers/libfuzzer/preinstall.sh | 1 + fuzzers/libfuzzer/run.sh | 2 +- fuzzers/libfuzzer/runonce.sh | 4 +++ magma/apply_patches.sh | 6 +++++ magma/coverage.sh | 36 +++++++++++++++++++++++++++ magma/fetch_target.sh | 5 +++- magma/prebuild.sh | 4 +++ magma/run.sh | 6 +++++ magma/src/source_coverage.c | 33 ++++++++++++++++++++++++ targets/libpng/build.sh | 2 +- targets/libtiff/build.sh | 2 +- targets/libxml2/build.sh | 2 +- targets/openssl/build.sh | 4 ++- targets/php/build.sh | 2 +- targets/php/preinstall.sh | 2 ++ targets/poppler/build.sh | 10 ++++---- targets/sqlite3/build.sh | 2 +- tools/captain/build.sh | 5 +++- tools/captain/captainrc | 4 +++ tools/captain/tests/report_2025.auto | 1 + tools/captain/tests/report_2025.debug | 5 ++-- 33 files changed, 217 insertions(+), 21 deletions(-) create mode 100644 fuzzers/aflplusplus/coverage.sh create mode 100644 fuzzers/honggfuzz/coverage.sh create mode 100644 fuzzers/libfuzzer/coverage.sh create mode 100755 magma/coverage.sh create mode 100644 magma/src/source_coverage.c diff --git a/docker/Dockerfile b/docker/Dockerfile index a093e0efe..7cebd9e59 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -16,6 +16,7 @@ ARG magma_root=./ ## Path variables inside the container ENV MAGMA_R=/magma ENV OUT=/magma_out +ENV COV=/magma_cov ENV SHARED=/magma_shared ENV CC=/usr/bin/gcc @@ -35,9 +36,9 @@ RUN mkdir -p /home && \ RUN echo "magma:amgam" | chpasswd && usermod -a -G sudo magma RUN echo "magma ALL=(ALL:ALL) NOPASSWD:ALL" >> /etc/sudoers -RUN mkdir -p ${SHARED} ${OUT} && \ - chown magma:magma ${SHARED} ${OUT} && \ - chmod 744 ${SHARED} ${OUT} +RUN mkdir -p ${SHARED} ${OUT} ${COV} && \ + chown magma:magma ${SHARED} ${OUT} ${COV} && \ + chmod 744 ${SHARED} ${OUT} ${COV} ARG magma_path=magma ENV MAGMA=${MAGMA_R}/${magma_path} @@ -91,6 +92,10 @@ ENV CXXFLAGS=${BUILD_FLAGS} ENV LIBS="-l:magma.o -lrt" ENV LDFLAGS="-L${OUT} -g" +ARG source_coverage +ENV SOURCE_COVERAGE=${source_coverage:+1} +ENV SOURCE_COVERAGE_FLAGS=${source_coverage:+"-fprofile-instr-generate -fcoverage-mapping"} + RUN ${FUZZER}/instrument.sh ENTRYPOINT ["/bin/bash", "-c", "${MAGMA}/run.sh"] diff --git a/fuzzers/aflplusplus/build.sh b/fuzzers/aflplusplus/build.sh index 9f7f9d22b..f2be00c23 100755 --- a/fuzzers/aflplusplus/build.sh +++ b/fuzzers/aflplusplus/build.sh @@ -19,4 +19,4 @@ export PYTHON_INCLUDE=/ make -j$(nproc) || exit 1 make -C utils/aflpp_driver || exit 1 -mkdir -p "$OUT/afl" "$OUT/cmplog" +mkdir -p "$OUT/afl" "$OUT/cmplog" "$COV/afl" diff --git a/fuzzers/aflplusplus/coverage.sh b/fuzzers/aflplusplus/coverage.sh new file mode 100644 index 000000000..4022d930b --- /dev/null +++ b/fuzzers/aflplusplus/coverage.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -e + +## +# Pre-requirements: +# - env SHARED: path to directory shared with host (to store results) +## + +export DIRECTORY_TO_SEARCH=$SHARED/findings/default/queue +chmod -R o+rx $SHARED/findings/default +export PATTERN_TO_MATCH="id:*" +cp $COV/afl/$PROGRAM $COV \ No newline at end of file diff --git a/fuzzers/aflplusplus/instrument.sh b/fuzzers/aflplusplus/instrument.sh index 7e30e9614..6c5929136 100755 --- a/fuzzers/aflplusplus/instrument.sh +++ b/fuzzers/aflplusplus/instrument.sh @@ -7,6 +7,8 @@ set -e # - env TARGET: path to target work dir # - env MAGMA: path to Magma support files # - env OUT: path to directory where artifacts are stored +# - env SOURCE_COVERAGE: if source-based code coverage is enabled +# - env COV: path to directory where artifacts for source-base code coverage are stored # - env CFLAGS and CXXFLAGS must be set to link against Magma instrumentation ## @@ -45,3 +47,14 @@ export LDFLAGS="$LDFLAGS -stdlib=libc++" # NOTE: We pass $OUT directly to the target build.sh script, since the artifact # itself is the fuzz target. In the case of Angora, we might need to # replace $OUT by $OUT/fast and $OUT/track, for instance. + +if [ ! -z $SOURCE_COVERAGE ]; then + export CC=clang + export CXX=clang++ + export CFLAGS="$SOURCE_COVERAGE_FLAGS" + export CXXFLAGS="$SOURCE_COVERAGE_FLAGS" + export LDFLAGS="$SOURCE_COVERAGE_FLAGS" + export LIBS="" + export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + OUT=$COV/afl TARGET=$COV "$TARGET/build.sh" +fi diff --git a/fuzzers/aflplusplus/preinstall.sh b/fuzzers/aflplusplus/preinstall.sh index 43b4c88e2..59c6b53bc 100755 --- a/fuzzers/aflplusplus/preinstall.sh +++ b/fuzzers/aflplusplus/preinstall.sh @@ -17,6 +17,7 @@ update-alternatives \ --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-profdata llvm-profdata /usr/bin/llvm-profdata-$LLVM_VERSION \ --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ diff --git a/fuzzers/aflplusplus/runonce.sh b/fuzzers/aflplusplus/runonce.sh index 1f269e3a4..732592f97 100755 --- a/fuzzers/aflplusplus/runonce.sh +++ b/fuzzers/aflplusplus/runonce.sh @@ -8,6 +8,7 @@ # - env OUT: path to directory where artifacts are stored # - env PROGRAM: name of program to run (should be found in $OUT) # - env ARGS: extra arguments to pass to the program +# - env SOURCE_COVERAGE: if source-based code coverage is enabled ## export TIMELIMIT=0.1s @@ -24,5 +25,8 @@ if [ -z "$args" ]; then args="'$1'" fi +if [ ! -z $SOURCE_COVERAGE ]; then + export LD_PRELOAD=$OUT/source_coverage.so +fi timeout -s KILL --preserve-status $TIMELIMIT bash -c \ "run_limited '$OUT/afl/$PROGRAM' $args" diff --git a/fuzzers/honggfuzz/coverage.sh b/fuzzers/honggfuzz/coverage.sh new file mode 100644 index 000000000..5489bba5b --- /dev/null +++ b/fuzzers/honggfuzz/coverage.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +## +# Pre-requirements: +# - env SHARED: path to directory shared with host (to store results) +## + +export DIRECTORY_TO_SEARCH=$SHARED/output +chmod -R o+rx $SHARED/output +export PATTERN_TO_MATCH="*" \ No newline at end of file diff --git a/fuzzers/honggfuzz/instrument.sh b/fuzzers/honggfuzz/instrument.sh index f2ef1dcfa..8137b341b 100755 --- a/fuzzers/honggfuzz/instrument.sh +++ b/fuzzers/honggfuzz/instrument.sh @@ -7,6 +7,8 @@ set -e # - env TARGET: path to target work dir # - env MAGMA: path to Magma support files # - env OUT: path to directory where artifacts are stored +# - env SOURCE_COVERAGE: if source-based code coverage is enabled +# - env COV: path to directory where artifacts for source-base code coverage are stored # - env CFLAGS and CXXFLAGS must be set to link against Magma instrumentation ## @@ -18,4 +20,15 @@ export CXX="$FUZZER/repo/hfuzz_cc/hfuzz-clang++" # NOTE: We pass $OUT directly to the target build.sh script, since the artifact # itself is the fuzz target. In the case of Angora, we might need to -# replace $OUT by $OUT/fast and $OUT/track, for instance. \ No newline at end of file +# replace $OUT by $OUT/fast and $OUT/track, for instance. + +if [ ! -z $SOURCE_COVERAGE ]; then + export CC=clang + export CXX=clang++ + export CFLAGS="$SOURCE_COVERAGE_FLAGS" + export CXXFLAGS="$SOURCE_COVERAGE_FLAGS" + export LDFLAGS="$SOURCE_COVERAGE_FLAGS" + export LIBS="" + export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + OUT=$COV TARGET=$COV "$TARGET/build.sh" +fi diff --git a/fuzzers/honggfuzz/preinstall.sh b/fuzzers/honggfuzz/preinstall.sh index 2a464a5a9..3c342187d 100755 --- a/fuzzers/honggfuzz/preinstall.sh +++ b/fuzzers/honggfuzz/preinstall.sh @@ -15,6 +15,7 @@ update-alternatives \ --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-profdata llvm-profdata /usr/bin/llvm-profdata-$LLVM_VERSION \ --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ diff --git a/fuzzers/honggfuzz/runonce.sh b/fuzzers/honggfuzz/runonce.sh index e4e29ad62..a5abd14ba 100755 --- a/fuzzers/honggfuzz/runonce.sh +++ b/fuzzers/honggfuzz/runonce.sh @@ -8,6 +8,7 @@ # - env OUT: path to directory where artifacts are stored # - env PROGRAM: name of program to run (should be found in $OUT) # - env ARGS: extra arguments to pass to the program +# - env SOURCE_COVERAGE: if source-based code coverage is enabled ## export TIMELIMIT=0.1s @@ -25,5 +26,8 @@ if [ -z "$args" ]; then args="'$1'" fi +if [ ! -z $SOURCE_COVERAGE ]; then + export LD_PRELOAD=$OUT/source_coverage.so +fi timeout -s KILL --preserve-status $TIMELIMIT bash -c \ "run_limited '$OUT/$PROGRAM' $args" \ No newline at end of file diff --git a/fuzzers/libfuzzer/coverage.sh b/fuzzers/libfuzzer/coverage.sh new file mode 100644 index 000000000..a1db28a1b --- /dev/null +++ b/fuzzers/libfuzzer/coverage.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -e + +## +# Pre-requirements: +# - env SHARED: path to directory shared with host (to store results) +## + +mkdir -p $SHARED/corpus +cp -r $TARGET/corpus/$PROGRAM $SHARED/corpus +export DIRECTORY_TO_SEARCH=$SHARED/corpus/$PROGRAM +chmod -R o+rx $SHARED/corpus/$PROGRAM +export PATTERN_TO_MATCH="*" \ No newline at end of file diff --git a/fuzzers/libfuzzer/instrument.sh b/fuzzers/libfuzzer/instrument.sh index 8a4371e29..47adab59b 100755 --- a/fuzzers/libfuzzer/instrument.sh +++ b/fuzzers/libfuzzer/instrument.sh @@ -7,6 +7,8 @@ set -e # - env TARGET: path to target work dir # - env MAGMA: path to Magma support files # - env OUT: path to directory where artifacts are stored +# - env SOURCE_COVERAGE: if source-based code coverage is enabled +# - env COV: path to directory where artifacts for source-base code coverage are stored # - env CFLAGS and CXXFLAGS must be set to link against Magma instrumentation ## @@ -25,3 +27,14 @@ export LIBS="$LIBS -l:driver.o $OUT/libFuzzer.a -lc++ -lc++abi" # NOTE: We pass $OUT directly to the target build.sh script, since the artifact # itself is the fuzz target. In the case of Angora, we might need to # replace $OUT by $OUT/fast and $OUT/track, for instance. + +if [ ! -z $SOURCE_COVERAGE ]; then + export CC=clang + export CXX=clang++ + export CFLAGS="$SOURCE_COVERAGE_FLAGS" + export CXXFLAGS="$SOURCE_COVERAGE_FLAGS" + export LDFLAGS="$SOURCE_COVERAGE_FLAGS" + export LIBS="" + export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + OUT=$COV TARGET=$COV "$TARGET/build.sh" +fi diff --git a/fuzzers/libfuzzer/preinstall.sh b/fuzzers/libfuzzer/preinstall.sh index 420f47cc8..0f08e6fad 100755 --- a/fuzzers/libfuzzer/preinstall.sh +++ b/fuzzers/libfuzzer/preinstall.sh @@ -17,6 +17,7 @@ update-alternatives \ --slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-$LLVM_VERSION \ --slave /usr/bin/llvm-c-test llvm-c-test /usr/bin/llvm-c-test-$LLVM_VERSION \ --slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-$LLVM_VERSION \ + --slave /usr/bin/llvm-profdata llvm-profdata /usr/bin/llvm-profdata-$LLVM_VERSION \ --slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-$LLVM_VERSION \ --slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-$LLVM_VERSION \ --slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-$LLVM_VERSION \ diff --git a/fuzzers/libfuzzer/run.sh b/fuzzers/libfuzzer/run.sh index 951fb5aca..1d7cd1a5a 100755 --- a/fuzzers/libfuzzer/run.sh +++ b/fuzzers/libfuzzer/run.sh @@ -11,7 +11,7 @@ # - env FUZZARGS: extra arguments to pass to the fuzzer ## -mkdir -p "$SHARED/findings" +mkdir -p "$SHARED/findings" "$SHARED/corpus" "$OUT/$PROGRAM" -rss_limit_mb=100 \ -fork=1 -ignore_timeouts=1 -ignore_crashes=1 -ignore_ooms=1 \ diff --git a/fuzzers/libfuzzer/runonce.sh b/fuzzers/libfuzzer/runonce.sh index 6ffea3182..07f4c0e1a 100755 --- a/fuzzers/libfuzzer/runonce.sh +++ b/fuzzers/libfuzzer/runonce.sh @@ -8,6 +8,7 @@ # - env OUT: path to directory where artifacts are stored # - env PROGRAM: name of program to run (should be found in $OUT) # - env ARGS: extra arguments to pass to the program +# - env SOURCE_COVERAGE: if source-based code coverage is enabled ## export TIMELIMIT=0.1s @@ -26,5 +27,8 @@ if [ -z "$args" ]; then args="'$1'" fi +if [ ! -z $SOURCE_COVERAGE ]; then + export LD_PRELOAD=$OUT/source_coverage.so +fi timeout -s KILL --preserve-status $TIMELIMIT bash -c \ "run_limited '$OUT/$PROGRAM' $args" \ No newline at end of file diff --git a/magma/apply_patches.sh b/magma/apply_patches.sh index e55c26e2b..01abf750e 100755 --- a/magma/apply_patches.sh +++ b/magma/apply_patches.sh @@ -16,3 +16,9 @@ while read patch; do name=${name%.patch} sed "s/%MAGMA_BUG%/$name/g" "$patch" | patch -p1 -d "$TARGET/repo" done + +find "$TARGET/patches/setup" -name "*.patch" | \ +while read patch; do + echo "Applying $patch" + cat $patch | patch -p1 -d "$COV/repo" +done diff --git a/magma/coverage.sh b/magma/coverage.sh new file mode 100755 index 000000000..302306b9e --- /dev/null +++ b/magma/coverage.sh @@ -0,0 +1,36 @@ +#!/bin/bash -ex + +## +# Pre-requirements: +# - env FUZZER: path to fuzzer work dir +# - env TARGET: path to target work dir +# - env SHARED: path to directory shared with host (to store results) +# - env PROGRAM: name of program to run (should be found in $OUT) +# - env COV: path to directory where artifacts for source-base code coverage are stored +## + +# load $DIRECTORY_TO_SEARCH and $PATTERN_TO_MATCH +source "$FUZZER/coverage.sh" + +# replay +seeds=() +readarray -d '' seeds < <(find $DIRECTORY_TO_SEARCH -type f -name "$PATTERN_TO_MATCH" -print0) +rm -f $COV/*profdata +for seed in ${seeds[@]}; do + seed_name=$(basename $seed) + export LLVM_PROFILE_FILE=$COV/$seed_name.profdata + export OUT=$COV + $FUZZER/runonce.sh $seed || continue +done + +export TARGET_NAME=$(basename $TARGET) + +# merge +llvm-profdata merge -output=$COV/$TARGET_NAME.profraw $COV/*.profdata +# show +llvm-cov show -format=html -output-dir=$SHARED/coverage-reports \ + -instr-profile $COV/$TARGET_NAME.profraw $COV/$PROGRAM +llvm-cov export -format=text -summary-only \ + -instr-profile $COV/$TARGET_NAME.profraw $COV/$PROGRAM > $SHARED/coverage-reports.json +chmod -R o+rx $SHARED/coverage-reports +echo "Dumped the source-based code coverage" diff --git a/magma/fetch_target.sh b/magma/fetch_target.sh index 48aa14164..8e5885dcf 100755 --- a/magma/fetch_target.sh +++ b/magma/fetch_target.sh @@ -36,4 +36,7 @@ elif [[ "$to_fetch" =~ \.tar\.gz(\?|$) ]]; then else echo "Unsupported link: $to_fetch" exit -fi \ No newline at end of file +fi + +cp -r "$TARGET"/repo "$COV"/repo +cp -r "$TARGET"/src "$COV"/src || echo "No such file or directory" diff --git a/magma/prebuild.sh b/magma/prebuild.sh index 602ba9d77..3f8e4374d 100755 --- a/magma/prebuild.sh +++ b/magma/prebuild.sh @@ -5,6 +5,7 @@ set -e # Pre-requirements: # - env MAGMA: path to Magma support files # - env OUT: path to directory where artifacts are stored +# - env COV: path to directory where artifacts for source-base code coverage are stored # - env SHARED: path to directory shared with host (to store results) ## @@ -17,3 +18,6 @@ $CC $CFLAGS -g -O0 -D"MAGMA_STORAGE=\"$MAGMA_STORAGE\"" "$MAGMA/src/monitor.c" \ "$OUT/pre_storage.o" -I "$MAGMA/src/" -o "$OUT/monitor" $LDFLAGS $LIBS rm "$OUT/pre_storage.o" + +$CC $CFLAGS -shared "$MAGMA/src/source_coverage.c" \ + -fPIC -o $COV/source_coverage.so -ldl diff --git a/magma/run.sh b/magma/run.sh index d6fcdd53e..b8673af7a 100755 --- a/magma/run.sh +++ b/magma/run.sh @@ -13,6 +13,7 @@ # - env TIMEOUT: time to run the campaign # - env MAGMA: path to Magma support files # + env LOGSIZE: size (in bytes) of log file to generate (default: 1 MiB) +# - env SOURCE_COVERAGE: if source-based code coverage is enabled ## # set default max log size to 1 MiB @@ -71,6 +72,7 @@ echo "Campaign launched at $(date '+%F %R')" timeout $TIMEOUT "$FUZZER/run.sh" | \ multilog n2 s$LOGSIZE "$SHARED/log" +chmod o+rx $SHARED/log if [ -f "$SHARED/log/current" ]; then cat "$SHARED/log/current" fi @@ -78,3 +80,7 @@ fi echo "Campaign terminated at $(date '+%F %R')" kill $(jobs -p) + +if [ ! -z $SOURCE_COVERAGE ]; then + $MAGMA/coverage.sh +fi diff --git a/magma/src/source_coverage.c b/magma/src/source_coverage.c new file mode 100644 index 000000000..0b0db1709 --- /dev/null +++ b/magma/src/source_coverage.c @@ -0,0 +1,33 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +static void clang_source_coverage_handler(int signum) { + fprintf(stderr, "DEBUG: Clang source coverage signal handler invoked (sig: %d).\n", signum); + return exit(0); +} + +static void clang_source_coverage_init(void) { + signal(SIGSEGV, clang_source_coverage_handler); + signal(SIGILL, clang_source_coverage_handler); + signal(SIGSTOP, clang_source_coverage_handler); + signal(SIGABRT, clang_source_coverage_handler); + fprintf(stderr, "DEBUG: Clang source coverage signal handler installed.\n"); +} + +int __libc_start_main( + int (*main)(int, char **, char **), + int argc, + char **argv, + int (*init)(int, char **, char **), + void (*fini)(void), + void (*rtld_fini)(void), + void *stack_end) +{ + typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main"); + + clang_source_coverage_init(); + return orig(main, argc, argv, init, fini, rtld_fini, stack_end); +} \ No newline at end of file diff --git a/targets/libpng/build.sh b/targets/libpng/build.sh index 4e9af56e9..22d7192dc 100755 --- a/targets/libpng/build.sh +++ b/targets/libpng/build.sh @@ -26,4 +26,4 @@ cp .libs/libpng16.a "$OUT/" $CXX $CXXFLAGS -std=c++11 -I. \ contrib/oss-fuzz/libpng_read_fuzzer.cc \ -o $OUT/libpng_read_fuzzer \ - $LDFLAGS .libs/libpng16.a $LIBS -lz \ No newline at end of file + $LDFLAGS .libs/libpng16.a $LIBS $LIB_FUZZING_ENGINE -lz diff --git a/targets/libtiff/build.sh b/targets/libtiff/build.sh index 479ec1609..861db23dd 100755 --- a/targets/libtiff/build.sh +++ b/targets/libtiff/build.sh @@ -32,4 +32,4 @@ cp "$WORK/bin/tiffcp" "$OUT/" $CXX $CXXFLAGS -std=c++11 -I$WORK/include \ contrib/oss-fuzz/tiff_read_rgba_fuzzer.cc -o $OUT/tiff_read_rgba_fuzzer \ $WORK/lib/libtiffxx.a $WORK/lib/libtiff.a -lz -ljpeg -Wl,-Bstatic -llzma -Wl,-Bdynamic \ - $LDFLAGS $LIBS + $LDFLAGS $LIBS $LIB_FUZZING_ENGINE diff --git a/targets/libxml2/build.sh b/targets/libxml2/build.sh index eefe22578..836529e0c 100755 --- a/targets/libxml2/build.sh +++ b/targets/libxml2/build.sh @@ -28,5 +28,5 @@ cp xmllint "$OUT/" for fuzzer in libxml2_xml_read_memory_fuzzer libxml2_xml_reader_for_file_fuzzer; do $CXX $CXXFLAGS -std=c++11 -Iinclude/ -I"$TARGET/src/" \ "$TARGET/src/$fuzzer.cc" -o "$OUT/$fuzzer" \ - .libs/libxml2.a $LDFLAGS $LIBS -lz -llzma -include limits + .libs/libxml2.a $LDFLAGS $LIBS $LIB_FUZZING_ENGINE -lz -llzma -include limits done diff --git a/targets/openssl/build.sh b/targets/openssl/build.sh index 6bed1e783..71cfc5b90 100755 --- a/targets/openssl/build.sh +++ b/targets/openssl/build.sh @@ -34,7 +34,9 @@ export LDLIBS="$LIBS" $CFLAGS -fno-sanitize=alignment $CONFIGURE_FLAGS make -j$(nproc) clean -make -j$(nproc) LDCMD="$CXX $CXXFLAGS" +set +e +make -j$(nproc) -k LDCMD="$CXX $CXXFLAGS" LDFLAGS="$LIB_FUZZING_ENGINE" +set -e fuzzers=$(find fuzz -executable -type f '!' -name \*.py '!' -name \*-test '!' -name \*.pl) for f in $fuzzers; do diff --git a/targets/php/build.sh b/targets/php/build.sh index efd30a5b5..c941c5821 100755 --- a/targets/php/build.sh +++ b/targets/php/build.sh @@ -39,7 +39,7 @@ export LDFLAGS="$LDFLAGS -pie" # Note: the acv_cv_func_fork=yes is needed to avoid the fork() # check in configure which fails when using the hongfuzz compiler -LIB_FUZZING_ENGINE="-Wall" ./configure \ +LIB_FUZZING_ENGINE="-Wall $LIB_FUZZING_ENGINE" ./configure \ --disable-all \ --enable-option-checking=fatal \ --enable-fuzzer \ diff --git a/targets/php/preinstall.sh b/targets/php/preinstall.sh index 77fc59b44..02d9dbbf1 100755 --- a/targets/php/preinstall.sh +++ b/targets/php/preinstall.sh @@ -7,3 +7,5 @@ apt-get update && \ # Dependency for PHP: oniguruma git clone https://github.com/kkos/oniguruma.git \ "$TARGET/oniguruma" + +cp -r $TARGET/oniguruma $COV/ diff --git a/targets/poppler/build.sh b/targets/poppler/build.sh index b79e61b46..1e4b485b3 100755 --- a/targets/poppler/build.sh +++ b/targets/poppler/build.sh @@ -24,9 +24,9 @@ cmake "$TARGET/repo" \ -DCMAKE_CXX_STANDARD=20 \ -DCMAKE_CXX_STANDARD_REQUIRED=ON \ -DCMAKE_CXX_EXTENSIONS=OFF \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS -stdlib=libc++" \ - -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ - -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS $LIBS -stdlib=libc++" \ + -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ + -DCMAKE_EXE_LINKER_FLAGS="$LDFLAGS $LIBS" \ + -DCMAKE_SHARED_LINKER_FLAGS="$LDFLAGS $LIBS" \ -DFREETYPE_LIBRARY=/usr/lib/x86_64-linux-gnu/libfreetype.so \ -DCMAKE_BUILD_TYPE=debug \ -DBUILD_SHARED_LIBS=OFF \ @@ -50,8 +50,8 @@ cmake "$TARGET/repo" \ make -j$(nproc) poppler poppler-cpp pdfimages pdftoppm cp "$WORK/poppler/utils/"{pdfimages,pdftoppm} "$OUT/" -$CXX $CXXFLAGS -std=c++20 -stdlib=libc++ \ +$CXX $CXXFLAGS -std=c++20 \ -I"$WORK/poppler/cpp" -I"$TARGET/repo/cpp" \ "$TARGET/src/pdf_fuzzer.cc" -o "$OUT/pdf_fuzzer" \ "$WORK/poppler/cpp/libpoppler-cpp.a" "$WORK/poppler/libpoppler.a" "/usr/lib/x86_64-linux-gnu/libfreetype.so" \ - $LDFLAGS $LIBS -ljpeg -lz -lopenjp2 -lpng -ltiff -llcms2 -lm -lpthread -pthread + $LDFLAGS $LIBS $LIB_FUZZING_ENGINE -ljpeg -lz -lopenjp2 -lpng -ltiff -llcms2 -lm -lpthread -pthread diff --git a/targets/sqlite3/build.sh b/targets/sqlite3/build.sh index b650ed288..7d935d9f4 100755 --- a/targets/sqlite3/build.sh +++ b/targets/sqlite3/build.sh @@ -36,4 +36,4 @@ make sqlite3.c $CC $CFLAGS -I. \ "$TARGET/repo/test/ossfuzz.c" "./sqlite3.o" \ -o "$OUT/sqlite3_fuzz" \ - $LDFLAGS $LIBS -pthread -ldl -lm + $LDFLAGS $LIBS $LIB_FUZZING_ENGINE -pthread -ldl -lm diff --git a/tools/captain/build.sh b/tools/captain/build.sh index 934b4b707..1807a8cb7 100755 --- a/tools/captain/build.sh +++ b/tools/captain/build.sh @@ -40,6 +40,9 @@ fi if [ ! -z $HARDEN ]; then harden_flag="--build-arg harden=1" fi +if [ ! -z $SOURCE_COVERAGE ]; then + coverage_flag="--build-arg source_coverage=1" +fi set -x docker build -t "$IMG_NAME" \ @@ -47,7 +50,7 @@ docker build -t "$IMG_NAME" \ --build-arg fuzzer_name="$FUZZER" \ --build-arg target_name="$TARGET" \ --build-arg target_version="$TARGET_VERSION" \ - $mode_flag $isan_flag $harden_flag \ + $mode_flag $isan_flag $harden_flag $coverage_flag \ -f "$MAGMA/docker/Dockerfile" "$MAGMA" set +x diff --git a/tools/captain/captainrc b/tools/captain/captainrc index 1ff9b1b1c..cbbd05d97 100644 --- a/tools/captain/captainrc +++ b/tools/captain/captainrc @@ -65,6 +65,10 @@ POLL=5 # (default: unset) # POC_EXTRACT=1 +# [SOURCE_COVERAGE]: if set, instrument the target for the source-based code +# coverage and obtain the coverage by replaying the corpus (default: unset) +# SOURCE_COVERAGE=1 + # [MAGMA_DEBUG]: if set, container entrypoint is switched to a shell. The fuzzer, # target and magma folders are mounted as volumes in a separate workdir. Useful # for investigating build issues. diff --git a/tools/captain/tests/report_2025.auto b/tools/captain/tests/report_2025.auto index 1e616d7d1..74d093d7b 100644 --- a/tools/captain/tests/report_2025.auto +++ b/tools/captain/tests/report_2025.auto @@ -8,6 +8,7 @@ WORKDIR=workdir_report_2025 REPEAT=10 TIMEOUT=24h ISAN=1 +SOURCE_COVERAGE=1 ### diff --git a/tools/captain/tests/report_2025.debug b/tools/captain/tests/report_2025.debug index de7191e11..7a86907c4 100644 --- a/tools/captain/tests/report_2025.debug +++ b/tools/captain/tests/report_2025.debug @@ -5,9 +5,10 @@ source captainrc WORKDIR=workdir_report_2025 -REPEAT=10 -TIMEOUT=24h +REPEAT=1 +TIMEOUT=10m ISAN=1 +SOURCE_COVERAGE=1 MAGMA_DEBUG=1 ### From b16b6bcf0e6c22c9d5068d0944720ffd9ad8cea0 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Sun, 1 Jun 2025 14:34:54 +0200 Subject: [PATCH 104/150] Add gen_cov_html.py - A poc html generation is added, not pretty, but kind of interative - Not all programs have valid coverage reports - Coverage overtime is missing --- tools/gen_cov_html.py | 170 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 tools/gen_cov_html.py diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py new file mode 100644 index 000000000..314189005 --- /dev/null +++ b/tools/gen_cov_html.py @@ -0,0 +1,170 @@ +import os +import json +import tarfile +import argparse +import pandas as pd +import plotly.express as px +import plotly.graph_objects as go + +ROOT_DIR = "captain/workdir_report_2025/ar" +CACHE_PATH = "coverage_data.pkl" + +records = [] + +def load_cov_data(): + # Step 1: Load data into DataFrame + for root, dirs, files in os.walk(ROOT_DIR): + if "coverage-reports.json" not in files and "ball.tar" in files: + tar_path = os.path.join(root, "ball.tar") + try: + with tarfile.open(tar_path) as tar: + tar.extractall(path=root) + print(f"Extracted ball.tar in {root}") + files = os.listdir(root) # refresh the file list after extraction + if "coverage-reports.json" not in files: + print(f"Failed to obtain coverage reports of {root}") + except Exception as e: + print(f"Failed to extract {tar_path}: {e}") + if "coverage-reports.json" in files: + json_path = os.path.join(root, "coverage-reports.json") + html_path = os.path.join(root, "coverage-reports/index.html") + parts = os.path.normpath(json_path).split(os.sep) + try: + fuzzer, target, program, run = parts[-5:-1] + except ValueError: + continue # skip non-matching paths + with open(json_path, "r") as f: + try: + data = json.load(f) + totals = data["data"][0]["totals"]["branches"] + record = { + "fuzzer": fuzzer, + "target": target, + "program": program, + "run": run, + "percent": totals["percent"], + "covered": totals["covered"], + "count": totals["count"], + "html_path": html_path + } + records.append(record) + except Exception as e: + print(f"Error parsing {json_path}: {e}") + + df = pd.DataFrame(records) + return df + +figures = [] + +def gen_figures(df: pd.DataFrame): + for (target, program), group in df.groupby(["target", "program"]): + # 1. Coverage Percentage Figure (Y = percent) + plot_df = group[["fuzzer", "percent"]].dropna() + fig_percent = px.box( + plot_df, + x="fuzzer", + y="percent", + points="all", + ) + + # 2. Covered Branches Figure (Y = covered) + plot_df = group[["fuzzer", "covered"]].dropna() + fig_covered = px.box( + plot_df, + x="fuzzer", + y="covered", + points="all", + ) + + # Collect both figures for display + links = group.apply( + lambda row: f'{row["fuzzer"]} / {row["run"]}', axis=1 + ).tolist() + + figures.append({ + "key": f"{target}/{program}", + "fig_percent": fig_percent.to_html(full_html=False, include_plotlyjs=True), + "fig_covered": fig_covered.to_html(full_html=False, include_plotlyjs=True), + "links": links + }) + +def plot_figures(): + html_parts = [ + "Coverage Summary", + '', + """ + + """, + "", + "

Coverage Summary

", + "" + ] + + for fig in figures: + html_parts.append(f"") + html_parts.append("") + html_parts.append(f"") + html_parts.append(f"") + html_parts.append("") + html_parts.append("") + + html_parts.append("

{fig['key']}

{fig['fig_percent']}{fig['fig_covered']}
    ") + for link in fig["links"]: + html_parts.append(f"
  • {link}
  • ") + html_parts.append("
") + + with open("coverage_summary.html", "w") as f: + f.write("\n".join(html_parts)) + print("HTML report generated.") + +def gen_cov_report(df: pd.DataFrame): + gen_figures(df) + plot_figures() + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate HTML coverage report.") + parser.add_argument("root_dir", help="Root directory containing coverage data") + args = parser.parse_args() + + ROOT_DIR = args.root_dir + + if os.path.exists(CACHE_PATH): + print("Loading cached DataFrame...") + df = pd.read_pickle(CACHE_PATH) + else: + print("Scanning {ROOTD_RI} for coverage-reports.json ...") + df = load_cov_data() + df.to_pickle(CACHE_PATH) + print("Saved DataFrame to cache.") + + gen_cov_report(df) + From 1bdd4f2e148e6082d81a447e69dcd9dde04f98f6 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Tue, 3 Jun 2025 16:39:26 +0200 Subject: [PATCH 105/150] Add coverage overtime --- .gitignore | 2 + magma/coverage.sh | 4 ++ magma/coverage_overtime.py | 93 +++++++++++++++++++++++++++++ tools/gen_cov_html.py | 116 ++++++++++++++++++++++++++++--------- 4 files changed, 188 insertions(+), 27 deletions(-) create mode 100644 magma/coverage_overtime.py diff --git a/.gitignore b/.gitignore index 6e5adfc46..6f8cce288 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ workdir* __pycache__/ +*.pkl +*.html diff --git a/magma/coverage.sh b/magma/coverage.sh index 302306b9e..af5006bb7 100755 --- a/magma/coverage.sh +++ b/magma/coverage.sh @@ -4,6 +4,7 @@ # Pre-requirements: # - env FUZZER: path to fuzzer work dir # - env TARGET: path to target work dir +# - env MAGMA: path to Magma support files # - env SHARED: path to directory shared with host (to store results) # - env PROGRAM: name of program to run (should be found in $OUT) # - env COV: path to directory where artifacts for source-base code coverage are stored @@ -23,6 +24,9 @@ for seed in ${seeds[@]}; do $FUZZER/runonce.sh $seed || continue done +python3 $MAGMA/coverage_overtime.py $DIRECTORY_TO_SEARCH $COV $COV/$PROGRAM --output $SHARED/coverage_overtime.txt +chmod o+rx $SHARED/coverage_overtime.txt + export TARGET_NAME=$(basename $TARGET) # merge diff --git a/magma/coverage_overtime.py b/magma/coverage_overtime.py new file mode 100644 index 000000000..97df0629c --- /dev/null +++ b/magma/coverage_overtime.py @@ -0,0 +1,93 @@ +import os +import argparse +import subprocess +import json +from datetime import datetime + +def get_timestamp(filepath): + return os.path.getmtime(filepath) + +def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): + """ + Given a single .profdata file, find all .profdata files in the same directory + that have a timestamp <= current file, and merge them into a .profraw. + """ + cov_dir = os.path.dirname(profdata_path) + + target_name = os.path.splitext(os.path.basename(profdata_path))[0] + profraw_path = os.path.join(cov_dir, f"{target_name}.profraw") + + # Collect all profdata files up to current timestamp + profdata_files = [ + os.path.join(cov_dir, f"{f}.profdata") + for f in os.listdir(corpus_dir) + if os.path.exists(os.path.join(cov_dir, f"{f}.profdata")) and os.path.getmtime(os.path.join(corpus_dir, f)) <= timestamp + ] + assert(profdata_path in profdata_files) + + if not profdata_files: + raise FileNotFoundError("No .profdata files found to merge.") + + cmd_merge = ["llvm-profdata", "merge", "-output", profraw_path] + profdata_files + result = subprocess.run(cmd_merge, capture_output=True, text=True) + if result.returncode != 0: + raise RuntimeError(f"llvm-profdata merge failed:\n{result.stderr}") + + return profraw_path + +def generate_json_report(profraw_path, binary_path, output_json_path): + cmd_cov = [ + "llvm-cov", "export", + "-format=text", + "-summary-only", + f"-instr-profile={profraw_path}", + binary_path + ] + result_cov = subprocess.run(cmd_cov, capture_output=True, text=True) + if result_cov.returncode != 0: + raise RuntimeError(f"llvm-cov export failed:\n{result_cov.stderr}") + + with open(output_json_path, "w") as f: + f.write(result_cov.stdout) + +def parse_coverage_from_json(json_path): + with open(json_path) as f: + data = json.load(f) + totals = data.get("data", [{}])[0].get("totals", {}) + branches = totals.get("branches", {}) + covered = branches.get("covered", 0) + percent = branches.get("percent", 0.0) + return covered, percent + +def main(corpus_dir, profdata_dir, binary_path, output_txt): + results = [] + for root, _, files in os.walk(profdata_dir): + for file in files: + if file.endswith(".profdata"): + profdata_path = os.path.join(root, file) + testcase_path = os.path.join(corpus_dir, os.path.splitext(file)[0]) + timestamp = get_timestamp(testcase_path) + + json_output = os.path.splitext(profdata_path)[0] + ".json" + try: + profraw_path = merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp); + generate_json_report(profraw_path, binary_path, json_output) + covered, percent = parse_coverage_from_json(json_output) + results.append((timestamp, covered, round(percent, 2))) + except Exception as e: + print(f"Error processing {profdata_path}: {e}") + + with open(output_txt, "w") as out: + out.write(f"timestamp,covered,percent\n") + for ts, covered, pct in sorted(results, key=lambda x: x[0]): + out.write(f"{ts},{covered},{pct}\n") + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate coverage summary from .profdata files.") + parser.add_argument("corpus_dir", help="Directory containing test cases") + parser.add_argument("profdata_dir", help="Directory containing .profdata files") + parser.add_argument("binary_path", help="Path to the instrumented binary") + parser.add_argument("--output", default="coverage_overtime.txt", help="Output summary .txt file") + + args = parser.parse_args() + main(args.corpus_dir, args.profdata_dir, args.binary_path, args.output) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index 314189005..46588b51f 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -7,9 +7,11 @@ import plotly.graph_objects as go ROOT_DIR = "captain/workdir_report_2025/ar" -CACHE_PATH = "coverage_data.pkl" +CACHE_PATH = "final_coverage.pkl" +COVERAGE_OVERTIME_CACHE_PATH = "coverage_overtime.pkl" records = [] +records_overtime = [] def load_cov_data(): # Step 1: Load data into DataFrame @@ -25,14 +27,16 @@ def load_cov_data(): print(f"Failed to obtain coverage reports of {root}") except Exception as e: print(f"Failed to extract {tar_path}: {e}") + if "coverage-reports.json" in files or "coverage_overtime.txt" in files: + try: + parts = os.path.normpath(root).split(os.sep) + fuzzer, target, program, run = parts[-4:] + except ValueError: + continue if "coverage-reports.json" in files: json_path = os.path.join(root, "coverage-reports.json") html_path = os.path.join(root, "coverage-reports/index.html") parts = os.path.normpath(json_path).split(os.sep) - try: - fuzzer, target, program, run = parts[-5:-1] - except ValueError: - continue # skip non-matching paths with open(json_path, "r") as f: try: data = json.load(f) @@ -50,31 +54,83 @@ def load_cov_data(): records.append(record) except Exception as e: print(f"Error parsing {json_path}: {e}") + if "coverage_overtime.txt" in files: + txt_path = os.path.join(root, "coverage_overtime.txt") + try: + df = pd.read_csv(txt_path) + df["timestamp"] = pd.to_numeric(df["timestamp"], errors="coerce") + df["timestamp"] = pd.to_datetime(df["timestamp"], unit="s", errors="coerce") + df = df.dropna(subset=["timestamp"]) + + df["timestamp"] = df["timestamp"].dt.floor("s") + df = df.drop_duplicates(subset="timestamp", keep="last") + df = df.sort_values("timestamp").reset_index(drop=True) + df = df.ffill() + + start_time = df['timestamp'].iloc[0] + df['timestamp'] = (df['timestamp'] - start_time).dt.total_seconds() + + df["fuzzer"] = fuzzer + df["target"] = target + df["program"] = program + df["run"] = run + records_overtime.append(df) + except Exception as e: + print(f"Failed to load {txt_path}: {e}") df = pd.DataFrame(records) - return df + df_overtime = pd.concat(records_overtime, ignore_index=True) + return df, df_overtime figures = [] -def gen_figures(df: pd.DataFrame): + + +def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): for (target, program), group in df.groupby(["target", "program"]): # 1. Coverage Percentage Figure (Y = percent) plot_df = group[["fuzzer", "percent"]].dropna() - fig_percent = px.box( - plot_df, - x="fuzzer", - y="percent", - points="all", - ) + fig_percent = px.box(plot_df, x="fuzzer", y="percent", points="all") # 2. Covered Branches Figure (Y = covered) plot_df = group[["fuzzer", "covered"]].dropna() - fig_covered = px.box( - plot_df, - x="fuzzer", - y="covered", - points="all", - ) + fig_covered = px.box(plot_df, x="fuzzer", y="covered", points="all") + + df_overtime = df_overtime[(df_overtime["target"] == target) & (df_overtime["program"] == program)] + # 3. Coverage Overtime Figure (Y = percent) + fig_percent_overtime = go.Figure() + for fuzzer, __group in df_overtime.groupby("fuzzer"): + stat = __group.groupby("timestamp")["percent"].agg(["mean", "min", "max"]).reset_index() + fig_percent_overtime.add_trace(go.Scatter( + x=stat["timestamp"], y=stat["mean"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) + fig_percent_overtime.add_trace(go.Scatter( + x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), + y=stat["max"].tolist() + stat["min"][::-1].tolist(), + fill='toself', + fillcolor='rgba(0,100,200,0.1)', + line=dict(color='rgba(255,255,255,0)'), + hoverinfo="skip", + name=f"{fuzzer} range", + showlegend=False + )) + fig_percent_overtime.update_layout(xaxis_title="Time") + # 4. Covered Branches Figure (Y = covered) + fig_covered_overtime = go.Figure() + for fuzzer, __group in df_overtime.groupby("fuzzer"): + stat = __group.groupby("timestamp")["covered"].agg(["mean", "min", "max"]).reset_index() + fig_covered_overtime.add_trace(go.Scatter( + x=stat["timestamp"], y=stat["mean"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) + fig_covered_overtime.add_trace(go.Scatter( + x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), + y=stat["max"].tolist() + stat["min"][::-1].tolist(), + fill='toself', + fillcolor='rgba(0,100,200,0.1)', + line=dict(color='rgba(255,255,255,0)'), + hoverinfo="skip", + name=f"{fuzzer} range", + showlegend=False + )) + fig_covered_overtime.update_layout(xaxis_title="Time") # Collect both figures for display links = group.apply( @@ -85,6 +141,8 @@ def gen_figures(df: pd.DataFrame): "key": f"{target}/{program}", "fig_percent": fig_percent.to_html(full_html=False, include_plotlyjs=True), "fig_covered": fig_covered.to_html(full_html=False, include_plotlyjs=True), + "fig_percent_overtime": fig_percent_overtime.to_html(full_html=False, include_plotlyjs=True), + "fig_covered_overtime": fig_covered_overtime.to_html(full_html=False, include_plotlyjs=True), "links": links }) @@ -130,24 +188,26 @@ def plot_figures(): ] for fig in figures: - html_parts.append(f"

{fig['key']}

") + html_parts.append(f"

{fig['key']}

") html_parts.append("") html_parts.append(f"{fig['fig_percent']}") html_parts.append(f"{fig['fig_covered']}") + html_parts.append(f"{fig['fig_percent_overtime']}") + html_parts.append(f"{fig['fig_covered_overtime']}") html_parts.append("") - html_parts.append("
    ") + html_parts.append("
      ") for link in fig["links"]: html_parts.append(f"
    • {link}
    • ") html_parts.append("
    ") html_parts.append("") - with open("coverage_summary.html", "w") as f: + with open("coverage.html", "w") as f: f.write("\n".join(html_parts)) print("HTML report generated.") -def gen_cov_report(df: pd.DataFrame): - gen_figures(df) +def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): + gen_figures(df, df_overtime) plot_figures() if __name__ == "__main__": @@ -160,11 +220,13 @@ def gen_cov_report(df: pd.DataFrame): if os.path.exists(CACHE_PATH): print("Loading cached DataFrame...") df = pd.read_pickle(CACHE_PATH) + df_overtime = pd.read_pickle(COVERAGE_OVERTIME_CACHE_PATH) else: - print("Scanning {ROOTD_RI} for coverage-reports.json ...") - df = load_cov_data() + print(f"Scanning {ROOT_DIR} for coverage-reports.json ...") + df, df_overtime = load_cov_data() df.to_pickle(CACHE_PATH) + df_overtime.to_pickle(COVERAGE_OVERTIME_CACHE_PATH) print("Saved DataFrame to cache.") - gen_cov_report(df) + gen_cov_report(df, df_overtime) From c2772ae0e8af03ceca28533c0a9d16cd9c5b7dc2 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Wed, 11 Jun 2025 14:39:59 +0200 Subject: [PATCH 106/150] Sample testcases for coverage one per minute --- magma/coverage.sh | 2 +- magma/coverage_overtime.py | 30 ++++++++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/magma/coverage.sh b/magma/coverage.sh index af5006bb7..a4883a2da 100755 --- a/magma/coverage.sh +++ b/magma/coverage.sh @@ -24,7 +24,7 @@ for seed in ${seeds[@]}; do $FUZZER/runonce.sh $seed || continue done -python3 $MAGMA/coverage_overtime.py $DIRECTORY_TO_SEARCH $COV $COV/$PROGRAM --output $SHARED/coverage_overtime.txt +python3 $MAGMA/coverage_overtime.py $DIRECTORY_TO_SEARCH $COV $COV/$PROGRAM 60 --output $SHARED/coverage_overtime.txt chmod o+rx $SHARED/coverage_overtime.txt export TARGET_NAME=$(basename $TARGET) diff --git a/magma/coverage_overtime.py b/magma/coverage_overtime.py index 97df0629c..fd4830e68 100644 --- a/magma/coverage_overtime.py +++ b/magma/coverage_overtime.py @@ -59,23 +59,32 @@ def parse_coverage_from_json(json_path): percent = branches.get("percent", 0.0) return covered, percent -def main(corpus_dir, profdata_dir, binary_path, output_txt): +def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): results = [] + last_sampled_time = 0 + + file_infos = [] for root, _, files in os.walk(profdata_dir): - for file in files: + for file in sorted(files): if file.endswith(".profdata"): profdata_path = os.path.join(root, file) testcase_path = os.path.join(corpus_dir, os.path.splitext(file)[0]) timestamp = get_timestamp(testcase_path) + file_infos.append((profdata_path, timestamp)) + file_infos.sort(key=lambda x: x[1]) + for profdata_path, timestamp in file_infos: + try: + # skip a few and always include the last one + if timestamp - last_sampled_time >= interval or timestamp == file_infos[-1][1]: json_output = os.path.splitext(profdata_path)[0] + ".json" - try: - profraw_path = merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp); - generate_json_report(profraw_path, binary_path, json_output) - covered, percent = parse_coverage_from_json(json_output) - results.append((timestamp, covered, round(percent, 2))) - except Exception as e: - print(f"Error processing {profdata_path}: {e}") + profraw_path = merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp); + generate_json_report(profraw_path, binary_path, json_output) + covered, percent = parse_coverage_from_json(json_output) + results.append((timestamp, covered, round(percent, 2))) + last_sampled_time = timestamp + except Exception as e: + print(f"Error processing {profdata_path}: {e}") with open(output_txt, "w") as out: out.write(f"timestamp,covered,percent\n") @@ -87,7 +96,8 @@ def main(corpus_dir, profdata_dir, binary_path, output_txt): parser.add_argument("corpus_dir", help="Directory containing test cases") parser.add_argument("profdata_dir", help="Directory containing .profdata files") parser.add_argument("binary_path", help="Path to the instrumented binary") + parser.add_argument("interval", help="Sample every `interval` seconds") parser.add_argument("--output", default="coverage_overtime.txt", help="Output summary .txt file") args = parser.parse_args() - main(args.corpus_dir, args.profdata_dir, args.binary_path, args.output) + main(args.corpus_dir, args.profdata_dir, args.binary_path, args.output, args.interval) From 972c57c314b271177f343b3021f465e7618e520d Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Wed, 11 Jun 2025 14:41:19 +0200 Subject: [PATCH 107/150] Fix data override and use median instead of mean --- tools/gen_cov_html.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index 46588b51f..927db0f21 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -87,6 +87,7 @@ def load_cov_data(): def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): + __df_overtime = df_overtime for (target, program), group in df.groupby(["target", "program"]): # 1. Coverage Percentage Figure (Y = percent) plot_df = group[["fuzzer", "percent"]].dropna() @@ -96,13 +97,13 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): plot_df = group[["fuzzer", "covered"]].dropna() fig_covered = px.box(plot_df, x="fuzzer", y="covered", points="all") - df_overtime = df_overtime[(df_overtime["target"] == target) & (df_overtime["program"] == program)] + df_overtime = __df_overtime[(__df_overtime["target"] == target) & (__df_overtime["program"] == program)] # 3. Coverage Overtime Figure (Y = percent) fig_percent_overtime = go.Figure() for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = __group.groupby("timestamp")["percent"].agg(["mean", "min", "max"]).reset_index() + stat = __group.groupby("timestamp")["percent"].agg(["median", "min", "max"]).reset_index() fig_percent_overtime.add_trace(go.Scatter( - x=stat["timestamp"], y=stat["mean"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) + x=stat["timestamp"], y=stat["median"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) fig_percent_overtime.add_trace(go.Scatter( x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), y=stat["max"].tolist() + stat["min"][::-1].tolist(), @@ -117,9 +118,9 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): # 4. Covered Branches Figure (Y = covered) fig_covered_overtime = go.Figure() for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = __group.groupby("timestamp")["covered"].agg(["mean", "min", "max"]).reset_index() + stat = __group.groupby("timestamp")["covered"].agg(["median", "min", "max"]).reset_index() fig_covered_overtime.add_trace(go.Scatter( - x=stat["timestamp"], y=stat["mean"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) + x=stat["timestamp"], y=stat["median"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) fig_covered_overtime.add_trace(go.Scatter( x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), y=stat["max"].tolist() + stat["min"][::-1].tolist(), From f50c8ff74ebeec80624ceccaa4a8e3c04e10356a Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Wed, 11 Jun 2025 16:47:03 +0200 Subject: [PATCH 108/150] Fix a few bugs when collecting coverage --- fuzzers/libfuzzer/coverage.sh | 4 ++-- magma/coverage_overtime.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/fuzzers/libfuzzer/coverage.sh b/fuzzers/libfuzzer/coverage.sh index a1db28a1b..2cc3134b4 100644 --- a/fuzzers/libfuzzer/coverage.sh +++ b/fuzzers/libfuzzer/coverage.sh @@ -7,7 +7,7 @@ set -e ## mkdir -p $SHARED/corpus -cp -r $TARGET/corpus/$PROGRAM $SHARED/corpus +cp -r -p $TARGET/corpus/$PROGRAM $SHARED/corpus export DIRECTORY_TO_SEARCH=$SHARED/corpus/$PROGRAM chmod -R o+rx $SHARED/corpus/$PROGRAM -export PATTERN_TO_MATCH="*" \ No newline at end of file +export PATTERN_TO_MATCH="*" diff --git a/magma/coverage_overtime.py b/magma/coverage_overtime.py index fd4830e68..c578663e1 100644 --- a/magma/coverage_overtime.py +++ b/magma/coverage_overtime.py @@ -86,6 +86,8 @@ def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): except Exception as e: print(f"Error processing {profdata_path}: {e}") + if len(results) == 0: + return with open(output_txt, "w") as out: out.write(f"timestamp,covered,percent\n") for ts, covered, pct in sorted(results, key=lambda x: x[0]): @@ -96,7 +98,7 @@ def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): parser.add_argument("corpus_dir", help="Directory containing test cases") parser.add_argument("profdata_dir", help="Directory containing .profdata files") parser.add_argument("binary_path", help="Path to the instrumented binary") - parser.add_argument("interval", help="Sample every `interval` seconds") + parser.add_argument("interval", help="Sample every `interval` seconds", type=int) parser.add_argument("--output", default="coverage_overtime.txt", help="Output summary .txt file") args = parser.parse_args() From b7e91aeee47d833cccee106b1c440569f7535069 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Thu, 12 Jun 2025 09:27:10 +0200 Subject: [PATCH 109/150] For libfuzzer, sync corpus seeds' timestamps --- fuzzers/libfuzzer/coverage.sh | 6 ++---- fuzzers/libfuzzer/run.sh | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fuzzers/libfuzzer/coverage.sh b/fuzzers/libfuzzer/coverage.sh index 2cc3134b4..9d0c8b40a 100644 --- a/fuzzers/libfuzzer/coverage.sh +++ b/fuzzers/libfuzzer/coverage.sh @@ -6,8 +6,6 @@ set -e # - env SHARED: path to directory shared with host (to store results) ## -mkdir -p $SHARED/corpus -cp -r -p $TARGET/corpus/$PROGRAM $SHARED/corpus -export DIRECTORY_TO_SEARCH=$SHARED/corpus/$PROGRAM -chmod -R o+rx $SHARED/corpus/$PROGRAM +export DIRECTORY_TO_SEARCH=$SHARED/corpus +chmod -R o+rx $SHARED/corpus export PATTERN_TO_MATCH="*" diff --git a/fuzzers/libfuzzer/run.sh b/fuzzers/libfuzzer/run.sh index 1d7cd1a5a..e95051416 100755 --- a/fuzzers/libfuzzer/run.sh +++ b/fuzzers/libfuzzer/run.sh @@ -12,8 +12,9 @@ ## mkdir -p "$SHARED/findings" "$SHARED/corpus" +cp $TARGET/corpus/$PROGRAM/* "$SHARED/corpus" "$OUT/$PROGRAM" -rss_limit_mb=100 \ -fork=1 -ignore_timeouts=1 -ignore_crashes=1 -ignore_ooms=1 \ -artifact_prefix="$SHARED/findings/" $FUZZARGS \ - "$TARGET/corpus/$PROGRAM" $ARGS + "$SHARED/corpus" $ARGS From d74e1cee851572b432fa292332b8c0cf7c7ebdd8 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Wed, 2 Jul 2025 13:45:28 +1000 Subject: [PATCH 110/150] Auto expand polls=("$MONITOR"/*) --- magma/run.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/magma/run.sh b/magma/run.sh index b8673af7a..2a3bda22e 100755 --- a/magma/run.sh +++ b/magma/run.sh @@ -47,7 +47,9 @@ fi # launch the fuzzer in parallel with the monitor rm -f "$MONITOR/tmp"* +shopt -s nullglob polls=("$MONITOR"/*) +shopt -u nullglob if [ ${#polls[@]} -eq 0 ]; then counter=0 else From df5f76e3352657b3504416cda02dd284c959d53b Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Wed, 2 Jul 2025 14:25:58 +1000 Subject: [PATCH 111/150] Add y labels for coverage over time figures --- tools/gen_cov_html.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index 927db0f21..606b5ba89 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -114,7 +114,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): name=f"{fuzzer} range", showlegend=False )) - fig_percent_overtime.update_layout(xaxis_title="Time") + fig_percent_overtime.update_layout(xaxis_title="Time", yaxis_title="percent") # 4. Covered Branches Figure (Y = covered) fig_covered_overtime = go.Figure() for fuzzer, __group in df_overtime.groupby("fuzzer"): @@ -131,7 +131,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): name=f"{fuzzer} range", showlegend=False )) - fig_covered_overtime.update_layout(xaxis_title="Time") + fig_covered_overtime.update_layout(xaxis_title="Time", yaxis_title="covered") # Collect both figures for display links = group.apply( From aab0f7a20d2ed4746c941f02b5d760a478ba2213 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 17 Jul 2025 07:44:03 +0530 Subject: [PATCH 112/150] Lint gen_cov + add cache option --- tools/gen_cov_html.py | 158 ++++++++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 52 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index 606b5ba89..d7bc2d66b 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -13,6 +13,7 @@ records = [] records_overtime = [] + def load_cov_data(): # Step 1: Load data into DataFrame for root, dirs, files in os.walk(ROOT_DIR): @@ -49,7 +50,7 @@ def load_cov_data(): "percent": totals["percent"], "covered": totals["covered"], "count": totals["count"], - "html_path": html_path + "html_path": html_path, } records.append(record) except Exception as e: @@ -59,7 +60,9 @@ def load_cov_data(): try: df = pd.read_csv(txt_path) df["timestamp"] = pd.to_numeric(df["timestamp"], errors="coerce") - df["timestamp"] = pd.to_datetime(df["timestamp"], unit="s", errors="coerce") + df["timestamp"] = pd.to_datetime( + df["timestamp"], unit="s", errors="coerce" + ) df = df.dropna(subset=["timestamp"]) df["timestamp"] = df["timestamp"].dt.floor("s") @@ -67,8 +70,8 @@ def load_cov_data(): df = df.sort_values("timestamp").reset_index(drop=True) df = df.ffill() - start_time = df['timestamp'].iloc[0] - df['timestamp'] = (df['timestamp'] - start_time).dt.total_seconds() + start_time = df["timestamp"].iloc[0] + df["timestamp"] = (df["timestamp"] - start_time).dt.total_seconds() df["fuzzer"] = fuzzer df["target"] = target @@ -82,8 +85,8 @@ def load_cov_data(): df_overtime = pd.concat(records_overtime, ignore_index=True) return df, df_overtime -figures = [] +figures = [] def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): @@ -97,55 +100,99 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): plot_df = group[["fuzzer", "covered"]].dropna() fig_covered = px.box(plot_df, x="fuzzer", y="covered", points="all") - df_overtime = __df_overtime[(__df_overtime["target"] == target) & (__df_overtime["program"] == program)] + df_overtime = __df_overtime[ + (__df_overtime["target"] == target) & (__df_overtime["program"] == program) + ] # 3. Coverage Overtime Figure (Y = percent) fig_percent_overtime = go.Figure() for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = __group.groupby("timestamp")["percent"].agg(["median", "min", "max"]).reset_index() - fig_percent_overtime.add_trace(go.Scatter( - x=stat["timestamp"], y=stat["median"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) - fig_percent_overtime.add_trace(go.Scatter( - x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), - y=stat["max"].tolist() + stat["min"][::-1].tolist(), - fill='toself', - fillcolor='rgba(0,100,200,0.1)', - line=dict(color='rgba(255,255,255,0)'), - hoverinfo="skip", - name=f"{fuzzer} range", - showlegend=False - )) - fig_percent_overtime.update_layout(xaxis_title="Time", yaxis_title="percent") + stat = ( + __group.groupby("timestamp")["percent"] + .agg(["median", "min", "max"]) + .reset_index() + ) + fig_percent_overtime.add_trace( + go.Scatter( + x=stat["timestamp"], + y=stat["median"], + mode="lines", + name=f"{fuzzer} avg", + line=dict(width=2), + ) + ) + fig_percent_overtime.add_trace( + go.Scatter( + x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), + y=stat["max"].tolist() + stat["min"][::-1].tolist(), + fill="toself", + fillcolor="rgba(0,100,200,0.1)", + line=dict(color="rgba(255,255,255,0)"), + hoverinfo="skip", + name=f"{fuzzer} range", + showlegend=False, + ) + ) + fig_percent_overtime.update_layout( + xaxis_title="Time", yaxis_title="percent" + ) # 4. Covered Branches Figure (Y = covered) fig_covered_overtime = go.Figure() for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = __group.groupby("timestamp")["covered"].agg(["median", "min", "max"]).reset_index() - fig_covered_overtime.add_trace(go.Scatter( - x=stat["timestamp"], y=stat["median"], mode="lines", name=f"{fuzzer} avg", line=dict(width=2))) - fig_covered_overtime.add_trace(go.Scatter( - x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), - y=stat["max"].tolist() + stat["min"][::-1].tolist(), - fill='toself', - fillcolor='rgba(0,100,200,0.1)', - line=dict(color='rgba(255,255,255,0)'), - hoverinfo="skip", - name=f"{fuzzer} range", - showlegend=False - )) - fig_covered_overtime.update_layout(xaxis_title="Time", yaxis_title="covered") + stat = ( + __group.groupby("timestamp")["covered"] + .agg(["median", "min", "max"]) + .reset_index() + ) + fig_covered_overtime.add_trace( + go.Scatter( + x=stat["timestamp"], + y=stat["median"], + mode="lines", + name=f"{fuzzer} avg", + line=dict(width=2), + ) + ) + fig_covered_overtime.add_trace( + go.Scatter( + x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), + y=stat["max"].tolist() + stat["min"][::-1].tolist(), + fill="toself", + fillcolor="rgba(0,100,200,0.1)", + line=dict(color="rgba(255,255,255,0)"), + hoverinfo="skip", + name=f"{fuzzer} range", + showlegend=False, + ) + ) + fig_covered_overtime.update_layout( + xaxis_title="Time", yaxis_title="covered" + ) # Collect both figures for display links = group.apply( - lambda row: f'{row["fuzzer"]} / {row["run"]}', axis=1 + lambda row: f'{row["fuzzer"]} / {row["run"]}', + axis=1, ).tolist() - figures.append({ - "key": f"{target}/{program}", - "fig_percent": fig_percent.to_html(full_html=False, include_plotlyjs=True), - "fig_covered": fig_covered.to_html(full_html=False, include_plotlyjs=True), - "fig_percent_overtime": fig_percent_overtime.to_html(full_html=False, include_plotlyjs=True), - "fig_covered_overtime": fig_covered_overtime.to_html(full_html=False, include_plotlyjs=True), - "links": links - }) + figures.append( + { + "key": f"{target}/{program}", + "fig_percent": fig_percent.to_html( + full_html=False, include_plotlyjs=True + ), + "fig_covered": fig_covered.to_html( + full_html=False, include_plotlyjs=True + ), + "fig_percent_overtime": fig_percent_overtime.to_html( + full_html=False, include_plotlyjs=True + ), + "fig_covered_overtime": fig_covered_overtime.to_html( + full_html=False, include_plotlyjs=True + ), + "links": links, + } + ) + def plot_figures(): html_parts = [ @@ -185,16 +232,17 @@ def plot_figures(): """, "", "

    Coverage Summary

    ", - "" + "
    ", ] for fig in figures: html_parts.append(f"") html_parts.append("") - html_parts.append(f"") - html_parts.append(f"") - html_parts.append(f"") - html_parts.append(f"") + html_parts.append(f"") + html_parts.append(f"") + html_parts.append("") + html_parts.append(f"") + html_parts.append(f"") html_parts.append("") html_parts.append("

    {fig['key']}

    {fig['fig_percent']}{fig['fig_covered']}{fig['fig_percent_overtime']}{fig['fig_covered_overtime']}{fig['fig_percent']}{fig['fig_covered']}
    {fig['fig_percent_overtime']}{fig['fig_covered_overtime']}
      ") for link in fig["links"]: @@ -207,18 +255,25 @@ def plot_figures(): f.write("\n".join(html_parts)) print("HTML report generated.") + def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): gen_figures(df, df_overtime) plot_figures() + if __name__ == "__main__": parser = argparse.ArgumentParser(description="Generate HTML coverage report.") - parser.add_argument("root_dir", help="Root directory containing coverage data") + parser.add_argument( + "--root_dir", help="Root directory containing coverage data", default=ROOT_DIR + ) + parser.add_argument( + "--cache", help="Use cached data if available", action="store_true" + ) args = parser.parse_args() ROOT_DIR = args.root_dir - if os.path.exists(CACHE_PATH): + if args.cache and os.path.exists(CACHE_PATH): print("Loading cached DataFrame...") df = pd.read_pickle(CACHE_PATH) df_overtime = pd.read_pickle(COVERAGE_OVERTIME_CACHE_PATH) @@ -228,6 +283,5 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): df.to_pickle(CACHE_PATH) df_overtime.to_pickle(COVERAGE_OVERTIME_CACHE_PATH) print("Saved DataFrame to cache.") - - gen_cov_report(df, df_overtime) + gen_cov_report(df, df_overtime) From 21b1eaf6e3dcaa41fc52d3e98114739907be7059 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 17 Jul 2025 08:06:38 +0530 Subject: [PATCH 113/150] Add option to build plots for specific targets --- tools/gen_cov_html.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index d7bc2d66b..9af61e593 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -14,7 +14,7 @@ records_overtime = [] -def load_cov_data(): +def load_cov_data(target_dir: str): # Step 1: Load data into DataFrame for root, dirs, files in os.walk(ROOT_DIR): if "coverage-reports.json" not in files and "ball.tar" in files: @@ -52,7 +52,8 @@ def load_cov_data(): "count": totals["count"], "html_path": html_path, } - records.append(record) + if target_dir == target or target_dir == "all": + records.append(record) except Exception as e: print(f"Error parsing {json_path}: {e}") if "coverage_overtime.txt" in files: @@ -77,7 +78,8 @@ def load_cov_data(): df["target"] = target df["program"] = program df["run"] = run - records_overtime.append(df) + if target_dir == target or target_dir == "all": + records_overtime.append(df) except Exception as e: print(f"Failed to load {txt_path}: {e}") @@ -266,6 +268,11 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): parser.add_argument( "--root_dir", help="Root directory containing coverage data", default=ROOT_DIR ) + parser.add_argument( + "--target", + help="Specify one target (default=all)", + default="all", + ) parser.add_argument( "--cache", help="Use cached data if available", action="store_true" ) @@ -279,7 +286,7 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): df_overtime = pd.read_pickle(COVERAGE_OVERTIME_CACHE_PATH) else: print(f"Scanning {ROOT_DIR} for coverage-reports.json ...") - df, df_overtime = load_cov_data() + df, df_overtime = load_cov_data(args.target) df.to_pickle(CACHE_PATH) df_overtime.to_pickle(COVERAGE_OVERTIME_CACHE_PATH) print("Saved DataFrame to cache.") From 3fc9977cb4aad42bb18a0c21dd6abf0e5a90a4e0 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 17 Jul 2025 10:47:57 +0530 Subject: [PATCH 114/150] Lint cov_overtime --- magma/coverage_overtime.py | 40 +++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/magma/coverage_overtime.py b/magma/coverage_overtime.py index c578663e1..f14a0c97b 100644 --- a/magma/coverage_overtime.py +++ b/magma/coverage_overtime.py @@ -2,11 +2,12 @@ import argparse import subprocess import json -from datetime import datetime + def get_timestamp(filepath): return os.path.getmtime(filepath) + def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): """ Given a single .profdata file, find all .profdata files in the same directory @@ -21,9 +22,10 @@ def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): profdata_files = [ os.path.join(cov_dir, f"{f}.profdata") for f in os.listdir(corpus_dir) - if os.path.exists(os.path.join(cov_dir, f"{f}.profdata")) and os.path.getmtime(os.path.join(corpus_dir, f)) <= timestamp + if os.path.exists(os.path.join(cov_dir, f"{f}.profdata")) + and os.path.getmtime(os.path.join(corpus_dir, f)) <= timestamp ] - assert(profdata_path in profdata_files) + assert profdata_path in profdata_files if not profdata_files: raise FileNotFoundError("No .profdata files found to merge.") @@ -35,13 +37,15 @@ def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): return profraw_path + def generate_json_report(profraw_path, binary_path, output_json_path): cmd_cov = [ - "llvm-cov", "export", + "llvm-cov", + "export", "-format=text", "-summary-only", f"-instr-profile={profraw_path}", - binary_path + binary_path, ] result_cov = subprocess.run(cmd_cov, capture_output=True, text=True) if result_cov.returncode != 0: @@ -50,6 +54,7 @@ def generate_json_report(profraw_path, binary_path, output_json_path): with open(output_json_path, "w") as f: f.write(result_cov.stdout) + def parse_coverage_from_json(json_path): with open(json_path) as f: data = json.load(f) @@ -59,6 +64,7 @@ def parse_coverage_from_json(json_path): percent = branches.get("percent", 0.0) return covered, percent + def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): results = [] last_sampled_time = 0 @@ -76,9 +82,14 @@ def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): for profdata_path, timestamp in file_infos: try: # skip a few and always include the last one - if timestamp - last_sampled_time >= interval or timestamp == file_infos[-1][1]: + if ( + timestamp - last_sampled_time >= interval + or timestamp == file_infos[-1][1] + ): json_output = os.path.splitext(profdata_path)[0] + ".json" - profraw_path = merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp); + profraw_path = merge_profdata_to_profraw( + corpus_dir, profdata_path, timestamp + ) generate_json_report(profraw_path, binary_path, json_output) covered, percent = parse_coverage_from_json(json_output) results.append((timestamp, covered, round(percent, 2))) @@ -89,17 +100,24 @@ def main(corpus_dir, profdata_dir, binary_path, output_txt, interval): if len(results) == 0: return with open(output_txt, "w") as out: - out.write(f"timestamp,covered,percent\n") + out.write("timestamp,covered,percent\n") for ts, covered, pct in sorted(results, key=lambda x: x[0]): out.write(f"{ts},{covered},{pct}\n") + if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Generate coverage summary from .profdata files.") + parser = argparse.ArgumentParser( + description="Generate coverage summary from .profdata files." + ) parser.add_argument("corpus_dir", help="Directory containing test cases") parser.add_argument("profdata_dir", help="Directory containing .profdata files") parser.add_argument("binary_path", help="Path to the instrumented binary") parser.add_argument("interval", help="Sample every `interval` seconds", type=int) - parser.add_argument("--output", default="coverage_overtime.txt", help="Output summary .txt file") + parser.add_argument( + "--output", default="coverage_overtime.txt", help="Output summary .txt file" + ) args = parser.parse_args() - main(args.corpus_dir, args.profdata_dir, args.binary_path, args.output, args.interval) + main( + args.corpus_dir, args.profdata_dir, args.binary_path, args.output, args.interval + ) From 75238c037aafadfc28dc144181d8c3b3775cc79b Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 18 Jul 2025 07:53:47 +0530 Subject: [PATCH 115/150] Gen cov HTML minor script improvements --- tools/gen_cov_html.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index 9af61e593..b295cefe0 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -16,7 +16,7 @@ def load_cov_data(target_dir: str): # Step 1: Load data into DataFrame - for root, dirs, files in os.walk(ROOT_DIR): + for root, _, files in os.walk(ROOT_DIR): if "coverage-reports.json" not in files and "ball.tar" in files: tar_path = os.path.join(root, "ball.tar") try: @@ -83,10 +83,13 @@ def load_cov_data(target_dir: str): except Exception as e: print(f"Failed to load {txt_path}: {e}") - df = pd.DataFrame(records) - df_overtime = pd.concat(records_overtime, ignore_index=True) - return df, df_overtime - + try: + df = pd.DataFrame(records) + df_overtime = pd.concat(records_overtime, ignore_index=True) + return df, df_overtime + except Exception as e: + print(f"Error creating DataFrame: {e}. Is the target directory correct?") + exit(1) figures = [] @@ -117,7 +120,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): go.Scatter( x=stat["timestamp"], y=stat["median"], - mode="lines", + mode="markers" if len(stat["timestamp"]) == 1 else "lines", name=f"{fuzzer} avg", line=dict(width=2), ) @@ -135,7 +138,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): ) ) fig_percent_overtime.update_layout( - xaxis_title="Time", yaxis_title="percent" + xaxis_title="Time", yaxis_title="Percent" ) # 4. Covered Branches Figure (Y = covered) fig_covered_overtime = go.Figure() @@ -149,7 +152,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): go.Scatter( x=stat["timestamp"], y=stat["median"], - mode="lines", + mode="markers" if len(stat["timestamp"]) == 1 else "lines", name=f"{fuzzer} avg", line=dict(width=2), ) @@ -167,7 +170,7 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): ) ) fig_covered_overtime.update_layout( - xaxis_title="Time", yaxis_title="covered" + xaxis_title="Time", yaxis_title="Covered" ) # Collect both figures for display From a73d2b85bfc238ddb3cc2124ebfa0011e9714c55 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 22 Jul 2025 10:50:32 +0530 Subject: [PATCH 116/150] Attempt 1: Interpolate overtime data with numpy --- tools/gen_cov_html.py | 131 ++++++++++++++++++++---------------------- 1 file changed, 62 insertions(+), 69 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index b295cefe0..fc781cce8 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -2,6 +2,7 @@ import json import tarfile import argparse +import numpy as np import pandas as pd import plotly.express as px import plotly.graph_objects as go @@ -12,6 +13,7 @@ records = [] records_overtime = [] +figures = [] def load_cov_data(target_dir: str): @@ -43,7 +45,7 @@ def load_cov_data(target_dir: str): data = json.load(f) totals = data["data"][0]["totals"]["branches"] record = { - "fuzzer": fuzzer, + "fuzzer": "afl++" if fuzzer == "aflplusplus" else fuzzer, "target": target, "program": program, "run": run, @@ -74,7 +76,7 @@ def load_cov_data(target_dir: str): start_time = df["timestamp"].iloc[0] df["timestamp"] = (df["timestamp"] - start_time).dt.total_seconds() - df["fuzzer"] = fuzzer + df["fuzzer"] = "afl++" if fuzzer == "aflplusplus" else fuzzer df["target"] = target df["program"] = program df["run"] = run @@ -91,11 +93,51 @@ def load_cov_data(target_dir: str): print(f"Error creating DataFrame: {e}. Is the target directory correct?") exit(1) -figures = [] + +def get_overtime_stats( + fuzzer_group: pd.DataFrame, time_grid: np.ndarray, stat_type: str +): + interpolated_runs = [] + for _, run_group in fuzzer_group.groupby("run"): + run_group = run_group.sort_values("timestamp") + interp = np.interp(time_grid, run_group["timestamp"], run_group[stat_type]) + interpolated_runs.append(interp) + + interp_runs_arr = np.array(interpolated_runs) + return { + "median": np.median(interp_runs_arr, axis=0), + "min": np.min(interp_runs_arr, axis=0), + "max": np.max(interp_runs_arr, axis=0), + } + + +def add_overtime_fuzzer_line( + figure: go.Figure, time_grid: np.ndarray, stats: dict, fuzzer: str +): + figure.add_trace( + go.Scatter( + x=time_grid, + y=stats["median"], + mode="markers" if len(time_grid) == 1 else "lines", + name=f"{fuzzer} avg", + line=dict(width=2), + ) + ) + figure.add_trace( + go.Scatter( + x=np.concatenate([time_grid, time_grid[::-1]]), + y=np.concatenate([stats["min"], stats["max"][::-1]]), + fill="toself", + fillcolor="rgba(0,100,200,0.1)", + line=dict(color="rgba(255,255,255,0)"), + hoverinfo="skip", + name=f"{fuzzer} range", + showlegend=False, + ) + ) def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): - __df_overtime = df_overtime for (target, program), group in df.groupby(["target", "program"]): # 1. Coverage Percentage Figure (Y = percent) plot_df = group[["fuzzer", "percent"]].dropna() @@ -105,73 +147,24 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): plot_df = group[["fuzzer", "covered"]].dropna() fig_covered = px.box(plot_df, x="fuzzer", y="covered", points="all") - df_overtime = __df_overtime[ - (__df_overtime["target"] == target) & (__df_overtime["program"] == program) - ] - # 3. Coverage Overtime Figure (Y = percent) + df_overtime_program = df_overtime.query( + "target == @target and program == @program" + ) + time_grid = np.arange(0, df_overtime_program["timestamp"].max() + 1, 1) + fig_percent_overtime = go.Figure() - for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = ( - __group.groupby("timestamp")["percent"] - .agg(["median", "min", "max"]) - .reset_index() - ) - fig_percent_overtime.add_trace( - go.Scatter( - x=stat["timestamp"], - y=stat["median"], - mode="markers" if len(stat["timestamp"]) == 1 else "lines", - name=f"{fuzzer} avg", - line=dict(width=2), - ) - ) - fig_percent_overtime.add_trace( - go.Scatter( - x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), - y=stat["max"].tolist() + stat["min"][::-1].tolist(), - fill="toself", - fillcolor="rgba(0,100,200,0.1)", - line=dict(color="rgba(255,255,255,0)"), - hoverinfo="skip", - name=f"{fuzzer} range", - showlegend=False, - ) - ) - fig_percent_overtime.update_layout( - xaxis_title="Time", yaxis_title="Percent" - ) - # 4. Covered Branches Figure (Y = covered) fig_covered_overtime = go.Figure() - for fuzzer, __group in df_overtime.groupby("fuzzer"): - stat = ( - __group.groupby("timestamp")["covered"] - .agg(["median", "min", "max"]) - .reset_index() - ) - fig_covered_overtime.add_trace( - go.Scatter( - x=stat["timestamp"], - y=stat["median"], - mode="markers" if len(stat["timestamp"]) == 1 else "lines", - name=f"{fuzzer} avg", - line=dict(width=2), - ) - ) - fig_covered_overtime.add_trace( - go.Scatter( - x=stat["timestamp"].tolist() + stat["timestamp"][::-1].tolist(), - y=stat["max"].tolist() + stat["min"][::-1].tolist(), - fill="toself", - fillcolor="rgba(0,100,200,0.1)", - line=dict(color="rgba(255,255,255,0)"), - hoverinfo="skip", - name=f"{fuzzer} range", - showlegend=False, - ) - ) - fig_covered_overtime.update_layout( - xaxis_title="Time", yaxis_title="Covered" - ) + for fuzzer, fuzzer_group in df_overtime_program.groupby("fuzzer"): + # 3. Coverage Overtime Figure (Y = percent) + stats_p = get_overtime_stats(fuzzer_group, time_grid, "percent") + add_overtime_fuzzer_line(fig_percent_overtime, time_grid, stats_p, fuzzer) + + # 4. Covered Branches Figure (Y = covered) + stats_c = get_overtime_stats(fuzzer_group, time_grid, "covered") + add_overtime_fuzzer_line(fig_covered_overtime, time_grid, stats_c, fuzzer) + + fig_percent_overtime.update_layout(xaxis_title="Time", yaxis_title="Percent") + fig_covered_overtime.update_layout(xaxis_title="Time", yaxis_title="Covered") # Collect both figures for display links = group.apply( From 1dc929387b75276ba877c1aed3de829a450a1d7c Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 22 Jul 2025 11:01:24 +0530 Subject: [PATCH 117/150] Allow specifiying multiple targets --- tools/gen_cov_html.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index fc781cce8..e66a38943 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -16,7 +16,7 @@ figures = [] -def load_cov_data(target_dir: str): +def load_cov_data(target_dirs: list): # Step 1: Load data into DataFrame for root, _, files in os.walk(ROOT_DIR): if "coverage-reports.json" not in files and "ball.tar" in files: @@ -54,7 +54,7 @@ def load_cov_data(target_dir: str): "count": totals["count"], "html_path": html_path, } - if target_dir == target or target_dir == "all": + if not len(target_dirs) or target in target_dirs: records.append(record) except Exception as e: print(f"Error parsing {json_path}: {e}") @@ -80,7 +80,7 @@ def load_cov_data(target_dir: str): df["target"] = target df["program"] = program df["run"] = run - if target_dir == target or target_dir == "all": + if not len(target_dirs) or target in target_dirs: records_overtime.append(df) except Exception as e: print(f"Failed to load {txt_path}: {e}") @@ -266,8 +266,9 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): ) parser.add_argument( "--target", - help="Specify one target (default=all)", - default="all", + help="Specify one or more targets (default=all)", + nargs="+", + default=[], ) parser.add_argument( "--cache", help="Use cached data if available", action="store_true" From c4bff1897170230a8f165ccda8353820b670861e Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Tue, 22 Jul 2025 11:18:18 +0530 Subject: [PATCH 118/150] Allow specifying outfile name --- tools/gen_cov_html.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gen_cov_html.py b/tools/gen_cov_html.py index e66a38943..57c245558 100644 --- a/tools/gen_cov_html.py +++ b/tools/gen_cov_html.py @@ -8,6 +8,7 @@ import plotly.graph_objects as go ROOT_DIR = "captain/workdir_report_2025/ar" +OUT_FILE = "coverage.html" CACHE_PATH = "final_coverage.pkl" COVERAGE_OVERTIME_CACHE_PATH = "coverage_overtime.pkl" @@ -249,7 +250,7 @@ def plot_figures(): html_parts.append("
    ") - with open("coverage.html", "w") as f: + with open(OUT_FILE, "w") as f: f.write("\n".join(html_parts)) print("HTML report generated.") @@ -264,6 +265,7 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): parser.add_argument( "--root_dir", help="Root directory containing coverage data", default=ROOT_DIR ) + parser.add_argument("--out_file", help="Output HTML file name", default=OUT_FILE) parser.add_argument( "--target", help="Specify one or more targets (default=all)", @@ -276,6 +278,7 @@ def gen_cov_report(df: pd.DataFrame, df_overtime: pd.DataFrame): args = parser.parse_args() ROOT_DIR = args.root_dir + OUT_FILE = args.out_file if args.cache and os.path.exists(CACHE_PATH): print("Loading cached DataFrame...") From 80eadf9f91adee3a2e7e8e4de0f9bd0fe037cd07 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Jul 2025 14:03:47 +0530 Subject: [PATCH 119/150] Fix openssl build with SOURCE_COVERAGE --- targets/openssl/build.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/openssl/build.sh b/targets/openssl/build.sh index 71cfc5b90..0bd8cdc4f 100755 --- a/targets/openssl/build.sh +++ b/targets/openssl/build.sh @@ -26,6 +26,7 @@ fi # the config script supports env var LDLIBS instead of LIBS export LDLIBS="$LIBS" +export LDFLAGS="$LDFLAGS $LIB_FUZZING_ENGINE" ./config --debug enable-fuzz-libfuzzer enable-fuzz-afl disable-tests -DPEDANTIC \ -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION no-shared no-module \ @@ -35,7 +36,7 @@ export LDLIBS="$LIBS" make -j$(nproc) clean set +e -make -j$(nproc) -k LDCMD="$CXX $CXXFLAGS" LDFLAGS="$LIB_FUZZING_ENGINE" +make -j$(nproc) -k LDCMD="$CXX $CXXFLAGS" set -e fuzzers=$(find fuzz -executable -type f '!' -name \*.py '!' -name \*-test '!' -name \*.pl) From 34977dfeb935995b557fa5516afc79e465bb7647 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 25 Jul 2025 14:04:51 +0530 Subject: [PATCH 120/150] Check if profdata files are valid before merging --- magma/coverage.sh | 9 ++++++++- magma/coverage_overtime.py | 29 ++++++++++++++++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/magma/coverage.sh b/magma/coverage.sh index a4883a2da..8d9962bb7 100755 --- a/magma/coverage.sh +++ b/magma/coverage.sh @@ -29,8 +29,15 @@ chmod o+rx $SHARED/coverage_overtime.txt export TARGET_NAME=$(basename $TARGET) +# filter valid profdata files before merging +VALID_PROFDATA=() +for f in "$COV"/*.profdata; do + if llvm-profdata show "$f" > /dev/null 2>&1; then + VALID_PROFDATA+=("$f") + fi +done # merge -llvm-profdata merge -output=$COV/$TARGET_NAME.profraw $COV/*.profdata +llvm-profdata merge -output=$COV/$TARGET_NAME.profraw "${VALID_PROFDATA[@]}" # show llvm-cov show -format=html -output-dir=$SHARED/coverage-reports \ -instr-profile $COV/$TARGET_NAME.profraw $COV/$PROGRAM diff --git a/magma/coverage_overtime.py b/magma/coverage_overtime.py index f14a0c97b..5af0f5057 100644 --- a/magma/coverage_overtime.py +++ b/magma/coverage_overtime.py @@ -8,6 +8,18 @@ def get_timestamp(filepath): return os.path.getmtime(filepath) +def is_valid_profdata(filepath): + try: + result = subprocess.run( + ["llvm-profdata", "show", filepath], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + return result.returncode == 0 + except Exception: + return False + + def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): """ Given a single .profdata file, find all .profdata files in the same directory @@ -18,13 +30,16 @@ def merge_profdata_to_profraw(corpus_dir, profdata_path, timestamp): target_name = os.path.splitext(os.path.basename(profdata_path))[0] profraw_path = os.path.join(cov_dir, f"{target_name}.profraw") - # Collect all profdata files up to current timestamp - profdata_files = [ - os.path.join(cov_dir, f"{f}.profdata") - for f in os.listdir(corpus_dir) - if os.path.exists(os.path.join(cov_dir, f"{f}.profdata")) - and os.path.getmtime(os.path.join(corpus_dir, f)) <= timestamp - ] + # Collect all valid profdata files up to current timestamp + profdata_files = [] + for f in os.listdir(corpus_dir): + path = os.path.join(cov_dir, f"{f}.profdata") + if ( + os.path.exists(path) + and os.path.getmtime(os.path.join(corpus_dir, f)) <= timestamp + ): + if is_valid_profdata(path): + profdata_files.append(path) assert profdata_path in profdata_files if not profdata_files: From 8d1e16de9a3b5ff87c9e82925eed752b434794da Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Thu, 21 Aug 2025 14:01:13 +0530 Subject: [PATCH 121/150] Organize scripts better in tools --- tools/{ => report_df}/gen_cov_html.py | 0 tools/{report_df => }/requirements.txt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tools/{ => report_df}/gen_cov_html.py (100%) rename tools/{report_df => }/requirements.txt (100%) diff --git a/tools/gen_cov_html.py b/tools/report_df/gen_cov_html.py similarity index 100% rename from tools/gen_cov_html.py rename to tools/report_df/gen_cov_html.py diff --git a/tools/report_df/requirements.txt b/tools/requirements.txt similarity index 100% rename from tools/report_df/requirements.txt rename to tools/requirements.txt From db55602e4ef292b4001098749fcd2fcf3a53ff10 Mon Sep 17 00:00:00 2001 From: Srividya Subramanian Date: Fri, 22 Aug 2025 11:55:25 +0530 Subject: [PATCH 122/150] Export plotly graphs to images ot make cov report static --- .gitignore | 1 + tools/report_df/gen_cov_html.py | 74 +++++++++++++++++++++++++-------- tools/requirements.txt | 12 +++++- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 6f8cce288..85cec6b85 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ workdir* __pycache__/ +cov_out/ *.pkl *.html diff --git a/tools/report_df/gen_cov_html.py b/tools/report_df/gen_cov_html.py index 57c245558..746beaa45 100644 --- a/tools/report_df/gen_cov_html.py +++ b/tools/report_df/gen_cov_html.py @@ -2,15 +2,21 @@ import json import tarfile import argparse +from pathlib import Path + import numpy as np import pandas as pd import plotly.express as px import plotly.graph_objects as go -ROOT_DIR = "captain/workdir_report_2025/ar" -OUT_FILE = "coverage.html" -CACHE_PATH = "final_coverage.pkl" -COVERAGE_OVERTIME_CACHE_PATH = "coverage_overtime.pkl" +ROOT_DIR = "../captain/workdir_report_2025/ar" +OUT_DIR = "cov_out" +OUT_FILE = f"{OUT_DIR}/coverage.html" +CACHE_PATH = f"{OUT_DIR}/final_coverage.pkl" +COVERAGE_OVERTIME_CACHE_PATH = f"{OUT_DIR}/coverage_overtime.pkl" + +IMG_DIR = f"{OUT_DIR}/assets" +IMG_FMT = "svg" records = [] records_overtime = [] @@ -138,6 +144,14 @@ def add_overtime_fuzzer_line( ) +def fig_to_img_tag(fig: go.Figure, name: str) -> str: + safe = "".join(c if c.isalnum() or c in "-_." else "_" for c in name) + out_path = os.path.join(IMG_DIR, f"{safe}.{IMG_FMT}") + fig.write_image(out_path, format=IMG_FMT, scale=2) + out_path = out_path.replace(f"{OUT_DIR}/", "") + return f'{safe}' + + def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): for (target, program), group in df.groupby(["target", "program"]): # 1. Coverage Percentage Figure (Y = percent) @@ -173,30 +187,39 @@ def gen_figures(df: pd.DataFrame, df_overtime: pd.DataFrame): axis=1, ).tolist() + base = f"{target}_{program}" + img_percent = fig_to_img_tag(fig_percent, f"{base}_percent_box") + img_covered = fig_to_img_tag(fig_covered, f"{base}_covered_box") + + if not df_overtime_program.empty and pd.notna( + df_overtime_program["timestamp"].max() + ): + img_percent_overtime = fig_to_img_tag( + fig_percent_overtime, f"{base}_percent_overtime" + ) + img_covered_overtime = fig_to_img_tag( + fig_covered_overtime, f"{base}_covered_overtime" + ) + else: + img_percent_overtime = "No overtime data" + img_covered_overtime = "No overtime data" + figures.append( { "key": f"{target}/{program}", - "fig_percent": fig_percent.to_html( - full_html=False, include_plotlyjs=True - ), - "fig_covered": fig_covered.to_html( - full_html=False, include_plotlyjs=True - ), - "fig_percent_overtime": fig_percent_overtime.to_html( - full_html=False, include_plotlyjs=True - ), - "fig_covered_overtime": fig_covered_overtime.to_html( - full_html=False, include_plotlyjs=True - ), + "fig_percent": img_percent, + "fig_covered": img_covered, + "fig_percent_overtime": img_percent_overtime, + "fig_covered_overtime": img_covered_overtime, "links": links, } ) + print(f"Generated figures for {target}/{program} with {len(group)} runs.") def plot_figures(): html_parts = [ "Coverage Summary", - '', """