mirror of
https://github.com/libarchive/libarchive.git
synced 2026-01-27 09:54:38 +00:00
Compare commits
304 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d1c9b95f1 | ||
|
|
dea03d6e00 | ||
|
|
3cd503b75a | ||
|
|
86851e3092 | ||
|
|
02eba33825 | ||
|
|
0bb2058bd5 | ||
|
|
e663efb430 | ||
|
|
3ff73fdfce | ||
|
|
e91171c9a0 | ||
|
|
7f27446a51 | ||
|
|
090fbc3655 | ||
|
|
8c2241a7e4 | ||
|
|
d54b2241b9 | ||
|
|
782cdd88b6 | ||
|
|
d1b87af584 | ||
|
|
9a089dc44a | ||
|
|
a55b8e8aec | ||
|
|
76558692a4 | ||
|
|
4a32d9ff7f | ||
|
|
998c0b4080 | ||
|
|
030a93817c | ||
|
|
9298dc503a | ||
|
|
e54c735586 | ||
|
|
b2d68e2f1a | ||
|
|
1cd0b9179c | ||
|
|
095609e89b | ||
|
|
5c84afd664 | ||
|
|
f366e98107 | ||
|
|
c4597a73f3 | ||
|
|
79fac84eb2 | ||
|
|
8042630d4f | ||
|
|
214ee3edc7 | ||
|
|
eb6f992ba1 | ||
|
|
544b07541b | ||
|
|
5e88593708 | ||
|
|
8f3fcf9ecd | ||
|
|
6e77f521fa | ||
|
|
50a67c9223 | ||
|
|
b39f91e5da | ||
|
|
55fbf225c8 | ||
|
|
e75e5892fd | ||
|
|
784b778f3b | ||
|
|
b51e59bcfb | ||
|
|
a7f3b56af6 | ||
|
|
cfb02de558 | ||
|
|
8295366f94 | ||
|
|
8c86c46d1b | ||
|
|
752df6abb7 | ||
|
|
728b43c0c1 | ||
|
|
0a594ab77d | ||
|
|
a819cc2829 | ||
|
|
1b9b42720f | ||
|
|
827905c93f | ||
|
|
aac59c1bd5 | ||
|
|
f49372e945 | ||
|
|
8ef2084104 | ||
|
|
e17f169356 | ||
|
|
47809f10bf | ||
|
|
81bc00a549 | ||
|
|
3150539edb | ||
|
|
8f7d334646 | ||
|
|
12522911fa | ||
|
|
1890755ab2 | ||
|
|
35aac8a925 | ||
|
|
fdec8c2f24 | ||
|
|
2df76f52c2 | ||
|
|
ce7b3f1c15 | ||
|
|
dbacda991c | ||
|
|
2caee6a37e | ||
|
|
d5bd2dfafe | ||
|
|
e1c3061b12 | ||
|
|
c2333a511d | ||
|
|
d8fba4df3a | ||
|
|
f75b5ddab0 | ||
|
|
02a76f2dc9 | ||
|
|
c5cc510145 | ||
|
|
ab09af7304 | ||
|
|
e929454ec8 | ||
|
|
3aa9c22ddf | ||
|
|
daf5abf802 | ||
|
|
f18a754d02 | ||
|
|
3396ba84d7 | ||
|
|
26c769ecdc | ||
|
|
45a873e998 | ||
|
|
fa5f70627c | ||
|
|
c45a07854d | ||
|
|
f80b1ae294 | ||
|
|
1435c4b20c | ||
|
|
989a303793 | ||
|
|
f02961f402 | ||
|
|
dc6c0c5f35 | ||
|
|
ce614c6524 | ||
|
|
8855146220 | ||
|
|
edbada88c0 | ||
|
|
212426e751 | ||
|
|
83c30ee813 | ||
|
|
d2e861769c | ||
|
|
89cbfe1028 | ||
|
|
1c08abc60d | ||
|
|
8fff509f1a | ||
|
|
d0f69b355d | ||
|
|
7976476c9f | ||
|
|
51b3e14257 | ||
|
|
33ac104169 | ||
|
|
de73860cda | ||
|
|
d207d816d0 | ||
|
|
12cdd35f31 | ||
|
|
e12c955dca | ||
|
|
46fe318edd | ||
|
|
582799ee57 | ||
|
|
b12d1c14d1 | ||
|
|
6d8e1a883c | ||
|
|
eb54a4d869 | ||
|
|
fda50c79ba | ||
|
|
372e709c1a | ||
|
|
4ecf62fbd7 | ||
|
|
c34ff01c02 | ||
|
|
2d987e725f | ||
|
|
7fdf32b6b2 | ||
|
|
98731ad500 | ||
|
|
be31ad37f3 | ||
|
|
619e22cae7 | ||
|
|
52bf0d7de0 | ||
|
|
36a530973a | ||
|
|
39dc43b3e0 | ||
|
|
638464b477 | ||
|
|
ab5cb61f49 | ||
|
|
38debf6be1 | ||
|
|
e1dea559c7 | ||
|
|
96f76577d3 | ||
|
|
e5c2eb783b | ||
|
|
a3787a34a8 | ||
|
|
a2933fbefd | ||
|
|
123d92bc3a | ||
|
|
ff3a0c37aa | ||
|
|
589659ed7f | ||
|
|
52db141ece | ||
|
|
3b1100f9a9 | ||
|
|
6bd863f612 | ||
|
|
4768f38535 | ||
|
|
3a072e0bb0 | ||
|
|
06191cd287 | ||
|
|
53135ca48e | ||
|
|
37ab51c2d3 | ||
|
|
ab4d21e4cb | ||
|
|
f12d80442c | ||
|
|
892f331450 | ||
|
|
bf50fe0538 | ||
|
|
2db13f7422 | ||
|
|
93f9e93d73 | ||
|
|
12ffcef28c | ||
|
|
02ebfb5a48 | ||
|
|
e099b418e3 | ||
|
|
6a008e524e | ||
|
|
835fe1133f | ||
|
|
466a2b5c7b | ||
|
|
640c9feced | ||
|
|
9e7af6f21c | ||
|
|
652a0c107b | ||
|
|
980b541632 | ||
|
|
8b3d3ee99b | ||
|
|
fb859e6d3f | ||
|
|
da65b39c06 | ||
|
|
e47c315f51 | ||
|
|
cb403667d7 | ||
|
|
0ff100c8d3 | ||
|
|
3bf1035e67 | ||
|
|
a335429c5e | ||
|
|
23ee781520 | ||
|
|
64bcf69ef8 | ||
|
|
ecce46744f | ||
|
|
6062470cbc | ||
|
|
aa1fc90ae5 | ||
|
|
d1418af239 | ||
|
|
cc97338239 | ||
|
|
ed2ada78a6 | ||
|
|
4dfaf2d359 | ||
|
|
cb6b9e9a28 | ||
|
|
d2d72ac78a | ||
|
|
b57d14f9c9 | ||
|
|
267042ebc7 | ||
|
|
a3d261a29a | ||
|
|
3c646995db | ||
|
|
7b59a6b693 | ||
|
|
e559754d6d | ||
|
|
82e247fe7c | ||
|
|
eff524fa4e | ||
|
|
84e8f3c98e | ||
|
|
4035fca93a | ||
|
|
3997a5f28a | ||
|
|
d01dc496d3 | ||
|
|
d06700a098 | ||
|
|
2db02ae6ae | ||
|
|
595fb29e4c | ||
|
|
609d8122f1 | ||
|
|
31cff981e4 | ||
|
|
d8aaf88c9f | ||
|
|
ee49ac8106 | ||
|
|
9fe18ba0a6 | ||
|
|
cd020d1ccb | ||
|
|
a474bab7e3 | ||
|
|
489d0b8e2f | ||
|
|
1e4b84ed30 | ||
|
|
50d44b4202 | ||
|
|
b1b3709cae | ||
|
|
ffde04f272 | ||
|
|
fd4ecc0146 | ||
|
|
a218a52dbb | ||
|
|
0de62cbda8 | ||
|
|
e4978e2edd | ||
|
|
40a89c7379 | ||
|
|
6a252c84a2 | ||
|
|
4984c652db | ||
|
|
664a20b6c7 | ||
|
|
b7066d4a6b | ||
|
|
6effe2ec6b | ||
|
|
251f7e839c | ||
|
|
47bdf82489 | ||
|
|
c3be70e071 | ||
|
|
9bdc5b82f7 | ||
|
|
475423a154 | ||
|
|
864c904442 | ||
|
|
dcf5475661 | ||
|
|
90c1e32a0d | ||
|
|
c0691458a0 | ||
|
|
75ef803092 | ||
|
|
0931c12b7e | ||
|
|
b1839a20e5 | ||
|
|
f3949062ed | ||
|
|
cdb45d71b2 | ||
|
|
fa85c7eaae | ||
|
|
aa69d34311 | ||
|
|
5a60d8cda4 | ||
|
|
ac66e0bc42 | ||
|
|
f2c3c790ff | ||
|
|
b7e1c617cb | ||
|
|
c40a3887ab | ||
|
|
9836e7e2fe | ||
|
|
a8f93f2480 | ||
|
|
b76c4042ae | ||
|
|
36bac92cd2 | ||
|
|
2764062e65 | ||
|
|
13700e1fb8 | ||
|
|
d7d1d19bb6 | ||
|
|
0f9a06d6ab | ||
|
|
1311a438a3 | ||
|
|
70978468e9 | ||
|
|
c7b7bd7c0e | ||
|
|
8d074302ac | ||
|
|
e1ca935c00 | ||
|
|
e1c0f9a660 | ||
|
|
20b4a4cb7c | ||
|
|
101230094c | ||
|
|
8540cb7cfb | ||
|
|
e2eda9e68b | ||
|
|
9ac39a0168 | ||
|
|
0a320b6a37 | ||
|
|
f90d036057 | ||
|
|
65d0393f24 | ||
|
|
e70e24a738 | ||
|
|
9b07a143ee | ||
|
|
cd5c44c5d0 | ||
|
|
2ed2db55e8 | ||
|
|
59b09796c3 | ||
|
|
d261f46ae5 | ||
|
|
dcdd7338d6 | ||
|
|
702f31a01c | ||
|
|
ebca997192 | ||
|
|
9d07162b08 | ||
|
|
33d3528723 | ||
|
|
715f7eac02 | ||
|
|
51b4c35bb3 | ||
|
|
6389d172ed | ||
|
|
ac96967e36 | ||
|
|
341dd5d1d4 | ||
|
|
18d456377e | ||
|
|
bc5f0884e3 | ||
|
|
101646e34e | ||
|
|
b6e1f06457 | ||
|
|
0685c77e83 | ||
|
|
5bb36db5e1 | ||
|
|
42c2f84649 | ||
|
|
6dbea2df3b | ||
|
|
a5d9c9a7cd | ||
|
|
cdc185e917 | ||
|
|
8b978a0368 | ||
|
|
bef52da622 | ||
|
|
8b763d872c | ||
|
|
51e66d32c6 | ||
|
|
4223b4c548 | ||
|
|
612223356e | ||
|
|
0ed4435209 | ||
|
|
992734d6cc | ||
|
|
627ba5bbbf | ||
|
|
2cdf47f332 | ||
|
|
d8ff8dd62c | ||
|
|
d6f6fdf979 | ||
|
|
38ac49553d | ||
|
|
9eacf09a86 | ||
|
|
0ddaa5f71c | ||
|
|
2961b132d0 | ||
|
|
182726d16a | ||
|
|
447201758e | ||
|
|
27588eba50 |
20
.cirrus.yml
20
.cirrus.yml
@ -1,3 +1,4 @@
|
||||
---
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
ARCH: amd64
|
||||
@ -9,10 +10,21 @@ FreeBSD_task:
|
||||
env:
|
||||
BS: cmake
|
||||
matrix:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-3
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-5
|
||||
- name: 15.0-STABLE (UFS)
|
||||
freebsd_instance:
|
||||
image_family: freebsd-15-0-amd64-ufs-snap
|
||||
- name: 15.0-RELEASE (UFS)
|
||||
freebsd_instance:
|
||||
image_family: freebsd-15-0-amd64-ufs
|
||||
- name: 15.0-RELEASE (ZFS)
|
||||
freebsd_instance:
|
||||
image_family: freebsd-15-0-amd64-zfs
|
||||
- name: 14.3-RELEASE
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-3
|
||||
- name: 13.5-RELEASE
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-5
|
||||
prepare_script:
|
||||
- ./build/ci/cirrus_ci/ci.sh prepare
|
||||
configure_script:
|
||||
|
||||
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
matrix:
|
||||
bs: [autotools, cmake]
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: Install dependencies
|
||||
run: ./build/ci/github_actions/install-macos-dependencies.sh
|
||||
- name: Autogen
|
||||
@ -47,7 +47,7 @@ jobs:
|
||||
run: ./build/ci/build.sh -a artifact
|
||||
env:
|
||||
BS: ${{ matrix.bs }}
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }}
|
||||
path: libarchive.tar.xz
|
||||
@ -59,7 +59,7 @@ jobs:
|
||||
bs: [autotools, cmake]
|
||||
crypto: [mbedtls, nettle, openssl]
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: Update apt cache
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
@ -93,14 +93,14 @@ jobs:
|
||||
run: ./build/ci/build.sh -a artifact
|
||||
env:
|
||||
BS: ${{ matrix.bs }}
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: libarchive-ubuntu-${{ matrix.bs }}-${{ matrix.crypto }}-${{ github.sha }}
|
||||
path: libarchive.tar.xz
|
||||
Ubuntu-distcheck:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: Update package definitions
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
@ -115,7 +115,7 @@ jobs:
|
||||
SKIP_OPEN_FD_ERR_TEST: 1
|
||||
- name: Dist-Artifact
|
||||
run: ./build/ci/build.sh -a dist-artifact
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: libarchive-${{ github.sha }}
|
||||
path: libarchive-dist.tar
|
||||
@ -127,7 +127,7 @@ jobs:
|
||||
matrix:
|
||||
be: [mingw-gcc, msvc]
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
- name: Install mingw
|
||||
if: ${{ matrix.be=='mingw-gcc' }}
|
||||
run: choco install mingw
|
||||
@ -163,7 +163,7 @@ jobs:
|
||||
shell: cmd
|
||||
env:
|
||||
BE: ${{ matrix.be }}
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: libarchive-windows-${{ matrix.be }}-${{ github.sha }}
|
||||
path: libarchive.zip
|
||||
|
||||
2
.github/workflows/cifuzz.yml
vendored
2
.github/workflows/cifuzz.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
fuzz-seconds: 600
|
||||
dry-run: false
|
||||
- name: Upload Crash
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
||||
8
.github/workflows/codeql.yml
vendored
8
.github/workflows/codeql.yml
vendored
@ -26,18 +26,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
|
||||
6
.github/workflows/scorecard.yml
vendored
6
.github/workflows/scorecard.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@ -60,6 +60,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6
|
||||
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
111
CMakeLists.txt
111
CMakeLists.txt
@ -19,7 +19,7 @@ endif()
|
||||
# MinSizeRel : Release Min Size build
|
||||
# None : No build type
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
# Set a value type to properly display CMAKE_BUILD_TYPE on GUI if the
|
||||
# value type is "UNINITIALIZED".
|
||||
@ -139,7 +139,12 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
# either of the following two, yet neither is supported as of 3.0.2
|
||||
# - check_linker_flag - does not exist
|
||||
# - try_compile - does not support linker flags
|
||||
IF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "SunOS")
|
||||
# SunOS linker doesn't support --gc-sections
|
||||
ELSE()
|
||||
# Place the functions and data into separate sections, allowing the linker
|
||||
# to garbage collect the unused ones.
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
||||
@ -148,10 +153,7 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
# Printing the discarded section is "too much", so enable on demand.
|
||||
#SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections")
|
||||
#SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -Wl,--print-gc-sections")
|
||||
ELSE()
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip")
|
||||
ENDIF(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
ENDIF()
|
||||
ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
CMAKE_C_COMPILER_ID MATCHES "^Clang$" AND NOT MSVC)
|
||||
IF (CMAKE_C_COMPILER_ID MATCHES "^XL$")
|
||||
@ -778,12 +780,22 @@ IF(ENABLE_CNG)
|
||||
LA_CHECK_INCLUDE_FILE("bcrypt.h" HAVE_BCRYPT_H)
|
||||
IF(HAVE_BCRYPT_H)
|
||||
LIST(APPEND ADDITIONAL_LIBS "bcrypt")
|
||||
# bcrypt supports these algorithms on all available versions
|
||||
SET(ARCHIVE_CRYPTO_MD5 1)
|
||||
SET(ARCHIVE_CRYPTO_MD5_WIN 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA1 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA1_WIN 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA256 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA256_WIN 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA384 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA384_WIN 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA512 1)
|
||||
SET(ARCHIVE_CRYPTO_SHA512_WIN 1)
|
||||
ENDIF(HAVE_BCRYPT_H)
|
||||
ELSE(ENABLE_CNG)
|
||||
UNSET(HAVE_BCRYPT_H CACHE)
|
||||
ENDIF(ENABLE_CNG)
|
||||
# Following files need windows.h, so we should test it after windows.h test.
|
||||
LA_CHECK_INCLUDE_FILE("wincrypt.h" HAVE_WINCRYPT_H)
|
||||
LA_CHECK_INCLUDE_FILE("winioctl.h" HAVE_WINIOCTL_H)
|
||||
|
||||
#
|
||||
@ -992,85 +1004,6 @@ main(int argc, char **argv)
|
||||
ENDFOREACH(ALGORITHM ${ALGORITHMS})
|
||||
ENDMACRO(CHECK_CRYPTO ALGORITHMS IMPLEMENTATION)
|
||||
|
||||
#
|
||||
# CRYPTO functions on Windows is defined at archive_windows.c, thus we do not
|
||||
# need the test what the functions can be mapped to archive_{crypto name}_init,
|
||||
# archive_{crypto name}_update and archive_{crypto name}_final.
|
||||
# The functions on Windows use CALG_{crypto name} macro to create a crypt object
|
||||
# and then we need to know what CALG_{crypto name} macros is available to show
|
||||
# ARCHIVE_CRYPTO_{crypto name}_WIN macros because Windows 2000 and earlier version
|
||||
# of Windows XP do not support SHA256, SHA384 and SHA512.
|
||||
#
|
||||
MACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
FOREACH(CRYPTO ${CRYPTO_LIST})
|
||||
IF(NOT ARCHIVE_CRYPTO_${CRYPTO})
|
||||
IF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
|
||||
STRING(TOUPPER "${CRYPTO}" crypto)
|
||||
SET(ALGID "")
|
||||
IF ("${CRYPTO}" MATCHES "^MD5$")
|
||||
SET(ALGID "CALG_MD5")
|
||||
ENDIF ("${CRYPTO}" MATCHES "^MD5$")
|
||||
IF ("${CRYPTO}" MATCHES "^SHA1$")
|
||||
SET(ALGID "CALG_SHA1")
|
||||
ENDIF ("${CRYPTO}" MATCHES "^SHA1$")
|
||||
IF ("${CRYPTO}" MATCHES "^SHA256$")
|
||||
SET(ALGID "CALG_SHA_256")
|
||||
ENDIF ("${CRYPTO}" MATCHES "^SHA256$")
|
||||
IF ("${CRYPTO}" MATCHES "^SHA384$")
|
||||
SET(ALGID "CALG_SHA_384")
|
||||
ENDIF ("${CRYPTO}" MATCHES "^SHA384$")
|
||||
IF ("${CRYPTO}" MATCHES "^SHA512$")
|
||||
SET(ALGID "CALG_SHA_512")
|
||||
ENDIF ("${CRYPTO}" MATCHES "^SHA512$")
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/config.h.in
|
||||
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h)
|
||||
FILE(READ "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/confdefs.h"
|
||||
CONFDEFS_H)
|
||||
|
||||
SET(SOURCE "${CONFDEFS_H}
|
||||
|
||||
#define ${crypto}_COMPILE_TEST
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
return ${ALGID};
|
||||
}
|
||||
")
|
||||
SET(SOURCE_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/check_crypto_win.c")
|
||||
|
||||
FILE(WRITE "${SOURCE_FILE}" "${SOURCE}")
|
||||
MESSAGE(STATUS "Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN")
|
||||
|
||||
TRY_COMPILE(ARCHIVE_CRYPTO_${CRYPTO}_WIN
|
||||
${CMAKE_BINARY_DIR}
|
||||
${SOURCE_FILE}
|
||||
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}/libarchive"
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
|
||||
IF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
|
||||
MESSAGE(STATUS
|
||||
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- found")
|
||||
SET(ARCHIVE_CRYPTO_${CRYPTO} 1)
|
||||
ELSE (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
|
||||
MESSAGE(STATUS
|
||||
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN -- not found")
|
||||
FILE(APPEND
|
||||
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
|
||||
"Checking support for ARCHIVE_CRYPTO_${CRYPTO}_WIN failed with the following output:\n"
|
||||
"${OUTPUT}\n"
|
||||
"Source file was:\n${SOURCE}\n")
|
||||
ENDIF (ARCHIVE_CRYPTO_${CRYPTO}_WIN)
|
||||
ENDIF(NOT DEFINED ARCHIVE_CRYPTO_${CRYPTO}_WIN)
|
||||
ENDIF(NOT ARCHIVE_CRYPTO_${CRYPTO})
|
||||
ENDFOREACH(CRYPTO)
|
||||
ENDIF(WIN32 AND NOT CYGWIN)
|
||||
ENDMACRO(CHECK_CRYPTO_WIN CRYPTO_LIST)
|
||||
|
||||
#
|
||||
# Find iconv
|
||||
# POSIX defines the second arg as const char **
|
||||
@ -1085,8 +1018,8 @@ MACRO(CHECK_ICONV LIB TRY_ICONV_CONST)
|
||||
CMAKE_C_COMPILER_ID MATCHES "^Clang$")
|
||||
#
|
||||
# During checking iconv proto type, we should use -Werror to avoid the
|
||||
# success of iconv detection with a warning which success is a miss
|
||||
# detection. So this needs for all build mode(even it's a release mode).
|
||||
# success of iconv detection with a warning, which would be a false
|
||||
# positive. So this is needed for all build modes, even in release mode.
|
||||
#
|
||||
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror")
|
||||
ENDIF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR
|
||||
@ -2184,8 +2117,6 @@ CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" OPENSSL)
|
||||
# Libmd has to be probed after OpenSSL.
|
||||
CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA512" LIBMD)
|
||||
|
||||
CHECK_CRYPTO_WIN("MD5;SHA1;SHA256;SHA384;SHA512")
|
||||
|
||||
# Check visibility annotations
|
||||
SET(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fvisibility=hidden -Werror")
|
||||
|
||||
8
NEWS
8
NEWS
@ -1,11 +1,3 @@
|
||||
Dec 01, 2025: libarchive 3.8.4 released
|
||||
|
||||
Nov 17, 2025: libarchive 3.8.3 released
|
||||
|
||||
Oct 15, 2025: libarchive 3.8.2 released
|
||||
|
||||
Jun 01, 2025: libarchive 3.8.1 released
|
||||
|
||||
May 20, 2025: libarchive 3.8.0 released
|
||||
|
||||
Mar 30, 2025: libarchive 3.7.9 released
|
||||
|
||||
@ -191,7 +191,7 @@ questions we are asked about libarchive:
|
||||
libraries. This also reduces the size of statically-linked
|
||||
binaries in environments where that matters.
|
||||
|
||||
* The library is generally _thread safe_ depending on the platform:
|
||||
* The library is generally _thread-safe_ depending on the platform:
|
||||
it does not define any global variables of its own. However, some
|
||||
platforms do not provide fully thread-safe versions of key C library
|
||||
functions. On those platforms, libarchive will use the non-thread-safe
|
||||
@ -214,7 +214,7 @@ questions we are asked about libarchive:
|
||||
multiple threads. Of course, those modules are completely
|
||||
optional and you can use the rest of libarchive without them.
|
||||
|
||||
* The library is _not_ thread aware, however. It does no locking
|
||||
* The library is _not_ thread-aware, however. It does no locking
|
||||
or thread management of any kind. If you create a libarchive
|
||||
object and need to access it from multiple threads, you will
|
||||
need to provide your own locking.
|
||||
|
||||
@ -1 +1 @@
|
||||
3008004
|
||||
3009000
|
||||
|
||||
@ -4,8 +4,8 @@ dnl First, define all of the version numbers up front.
|
||||
dnl In particular, this allows the version macro to be used in AC_INIT
|
||||
|
||||
dnl These first two version numbers are updated automatically on each release.
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.8.4])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3008004])
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.9.0dev])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3009000])
|
||||
|
||||
dnl bsdtar and bsdcpio versioning tracks libarchive
|
||||
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
|
||||
@ -377,7 +377,7 @@ AC_CHECK_HEADERS([time.h unistd.h utime.h wchar.h wctype.h])
|
||||
AC_CHECK_TYPE([suseconds_t])
|
||||
AC_CHECK_HEADERS([windows.h])
|
||||
# check windows.h first; the other headers require it.
|
||||
AC_CHECK_HEADERS([wincrypt.h winioctl.h],[],[],
|
||||
AC_CHECK_HEADERS([winioctl.h],[],[],
|
||||
[[#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,8 @@ LOCAL_PATH := $(subst /contrib/android,,$(call my-dir))
|
||||
libarchive_target_config := contrib/android/config/android.h
|
||||
|
||||
libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_blake2s_ref.c \
|
||||
libarchive/archive_blake2sp_ref.c \
|
||||
libarchive/archive_check_magic.c \
|
||||
libarchive/archive_cmdline.c \
|
||||
libarchive/archive_cryptor.c \
|
||||
@ -44,6 +46,7 @@ libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_parse_date.c \
|
||||
libarchive/archive_pathmatch.c \
|
||||
libarchive/archive_ppmd7.c \
|
||||
libarchive/archive_ppmd8.c \
|
||||
libarchive/archive_random.c \
|
||||
libarchive/archive_rb.c \
|
||||
libarchive/archive_read.c \
|
||||
@ -86,6 +89,7 @@ libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_read_support_format_lha.c \
|
||||
libarchive/archive_read_support_format_mtree.c \
|
||||
libarchive/archive_read_support_format_rar.c \
|
||||
libarchive/archive_read_support_format_rar5.c \
|
||||
libarchive/archive_read_support_format_raw.c \
|
||||
libarchive/archive_read_support_format_tar.c \
|
||||
libarchive/archive_read_support_format_warc.c \
|
||||
@ -93,6 +97,7 @@ libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_read_support_format_zip.c \
|
||||
libarchive/archive_string.c \
|
||||
libarchive/archive_string_sprintf.c \
|
||||
libarchive/archive_time.c \
|
||||
libarchive/archive_util.c \
|
||||
libarchive/archive_version_details.c \
|
||||
libarchive/archive_virtual.c \
|
||||
@ -123,7 +128,9 @@ libarchive_src_files := libarchive/archive_acl.c \
|
||||
libarchive/archive_write_set_format_ar.c \
|
||||
libarchive/archive_write_set_format_by_name.c \
|
||||
libarchive/archive_write_set_format_cpio.c \
|
||||
libarchive/archive_write_set_format_cpio_binary.c \
|
||||
libarchive/archive_write_set_format_cpio_newc.c \
|
||||
libarchive/archive_write_set_format_cpio_odc.c \
|
||||
libarchive/archive_write_set_format_iso9660.c \
|
||||
libarchive/archive_write_set_format_mtree.c \
|
||||
libarchive/archive_write_set_format_pax.c \
|
||||
@ -305,4 +312,17 @@ LOCAL_SRC_FILES := $(bsdcat_src_files)
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := bsdtar-recovery
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_STEM := bsdtar
|
||||
LOCAL_CFLAGS := -DBSDTAR_VERSION_STRING=ARCHIVE_VERSION_ONLY_STRING -DPLATFORM_CONFIG_H=\"$(libarchive_target_config)\"
|
||||
LOCAL_STATIC_LIBRARIES := libarchive libarchive_fe libz
|
||||
LOCAL_SRC_FILES := $(bsdtar_src_files)
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libarchive $(LOCAL_PATH)/libarchive_fe $(LOCAL_PATH)/contrib/android/include
|
||||
LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
|
||||
LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
endif
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#ifndef ARCHIVE_PLATFORM_H_ANDROID_INCLUDED
|
||||
#define ARCHIVE_PLATFORM_H_ANDROID_INCLUDED
|
||||
|
||||
#define __LIBARCHIVE_CONFIG_H_INCLUDED 1
|
||||
|
||||
#include <android/api-level.h>
|
||||
#ifdef __ANDROID_API__
|
||||
#if __ANDROID_API__ > 20
|
||||
@ -40,8 +42,8 @@
|
||||
|
||||
#define HAVE_CHOWN 1
|
||||
#define HAVE_CHROOT 1
|
||||
#define HAVE_CLOSEFROM 1
|
||||
#define HAVE_CLOSE_RANGE 1
|
||||
#define HAVE_CLOSEFROM 0
|
||||
#define HAVE_CLOSE_RANGE 0
|
||||
#define HAVE_CTIME_R 1
|
||||
#define HAVE_CTYPE_H 1
|
||||
#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0
|
||||
@ -55,6 +57,8 @@
|
||||
#define HAVE_DECL_UINTMAX_MAX 1
|
||||
#define HAVE_DECL_UINT32_MAX 1
|
||||
#define HAVE_DECL_UINT64_MAX 1
|
||||
#define HAVE_DECL_INT32_MAX 1
|
||||
#define HAVE_DECL_INT32_MIN 1
|
||||
#define HAVE_DIRENT_H 1
|
||||
#define HAVE_DIRFD 1
|
||||
#define HAVE_DLFCN_H 1
|
||||
@ -137,7 +141,7 @@
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_STRRCHR 1
|
||||
#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
|
||||
#define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
|
||||
#define HAVE_STRUCT_STAT_ST_MTIME_NSEC 0
|
||||
#define HAVE_STRUCT_TM_TM_GMTOFF 1
|
||||
#define HAVE_SYMLINK 1
|
||||
#define HAVE_SYS_CDEFS_H 1
|
||||
|
||||
@ -899,9 +899,6 @@
|
||||
/* Define to 1 if you have the <wctype.h> header file. */
|
||||
#define HAVE_WCTYPE_H 1
|
||||
|
||||
/* Define to 1 if you have the <wincrypt.h> header file. */
|
||||
#define HAVE_WINCRYPT_H 1
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#define HAVE_WINDOWS_H 1
|
||||
|
||||
|
||||
156
contrib/oss-fuzz/fuzz_helpers.h
Normal file
156
contrib/oss-fuzz/fuzz_helpers.h
Normal file
@ -0,0 +1,156 @@
|
||||
// Copyright 2024 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBARCHIVE_FUZZ_HELPERS_H_
|
||||
#define LIBARCHIVE_FUZZ_HELPERS_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <ftw.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
// Default maximum input size for fuzzers
|
||||
static constexpr size_t kDefaultMaxInputSize = 256 * 1024; // 256KB
|
||||
|
||||
// Buffer structure for archive reading callbacks
|
||||
struct Buffer {
|
||||
const uint8_t* data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
// Archive read callback function
|
||||
static la_ssize_t reader_callback(struct archive* a, void* client_data,
|
||||
const void** buffer) {
|
||||
(void)a;
|
||||
Buffer* buf = static_cast<Buffer*>(client_data);
|
||||
|
||||
if (buf->pos >= buf->size) {
|
||||
return 0; // EOF
|
||||
}
|
||||
|
||||
*buffer = buf->data + buf->pos;
|
||||
size_t remaining = buf->size - buf->pos;
|
||||
buf->pos = buf->size; // Consume all remaining data
|
||||
return static_cast<la_ssize_t>(remaining);
|
||||
}
|
||||
|
||||
// Helper class for consuming fuzz data in structured ways
|
||||
class DataConsumer {
|
||||
public:
|
||||
DataConsumer(const uint8_t* data, size_t size)
|
||||
: data_(data), size_(size), pos_(0) {}
|
||||
|
||||
bool empty() const { return pos_ >= size_; }
|
||||
size_t remaining() const { return size_ - pos_; }
|
||||
|
||||
uint8_t consume_byte() {
|
||||
if (pos_ >= size_) return 0;
|
||||
return data_[pos_++];
|
||||
}
|
||||
|
||||
uint16_t consume_u16() {
|
||||
uint16_t val = 0;
|
||||
if (pos_ + 2 <= size_) {
|
||||
val = static_cast<uint16_t>(data_[pos_]) |
|
||||
(static_cast<uint16_t>(data_[pos_ + 1]) << 8);
|
||||
pos_ += 2;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t consume_u32() {
|
||||
uint32_t val = 0;
|
||||
if (pos_ + 4 <= size_) {
|
||||
val = static_cast<uint32_t>(data_[pos_]) |
|
||||
(static_cast<uint32_t>(data_[pos_ + 1]) << 8) |
|
||||
(static_cast<uint32_t>(data_[pos_ + 2]) << 16) |
|
||||
(static_cast<uint32_t>(data_[pos_ + 3]) << 24);
|
||||
pos_ += 4;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int64_t consume_i64() {
|
||||
int64_t val = 0;
|
||||
if (pos_ + 8 <= size_) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
val |= static_cast<int64_t>(data_[pos_ + i]) << (8 * i);
|
||||
}
|
||||
pos_ += 8;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// Consume a null-terminated string up to max_len characters
|
||||
// Returns pointer to internal buffer (valid until next consume_string call)
|
||||
const char* consume_string(size_t max_len) {
|
||||
if (max_len > sizeof(string_buf_) - 1) {
|
||||
max_len = sizeof(string_buf_) - 1;
|
||||
}
|
||||
size_t avail = size_ - pos_;
|
||||
size_t len = (avail < max_len) ? avail : max_len;
|
||||
size_t actual_len = 0;
|
||||
|
||||
while (actual_len < len && pos_ < size_) {
|
||||
char c = static_cast<char>(data_[pos_++]);
|
||||
if (c == '\0') break;
|
||||
string_buf_[actual_len++] = c;
|
||||
}
|
||||
string_buf_[actual_len] = '\0';
|
||||
return string_buf_;
|
||||
}
|
||||
|
||||
// Consume raw bytes into a buffer
|
||||
size_t consume_bytes(void* out, size_t len) {
|
||||
size_t avail = size_ - pos_;
|
||||
size_t to_copy = (avail < len) ? avail : len;
|
||||
if (to_copy > 0) {
|
||||
memcpy(out, data_ + pos_, to_copy);
|
||||
pos_ += to_copy;
|
||||
}
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
// Get remaining data as a buffer
|
||||
const uint8_t* remaining_data() const {
|
||||
return data_ + pos_;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t* data_;
|
||||
size_t size_;
|
||||
size_t pos_;
|
||||
char string_buf_[512];
|
||||
};
|
||||
|
||||
// Callback for nftw to remove files/directories
|
||||
static int remove_callback(const char* fpath, const struct stat* sb,
|
||||
int typeflag, struct FTW* ftwbuf) {
|
||||
(void)sb;
|
||||
(void)typeflag;
|
||||
(void)ftwbuf;
|
||||
return remove(fpath);
|
||||
}
|
||||
|
||||
// Recursively remove a directory tree (safer than system("rm -rf ..."))
|
||||
static int remove_directory_tree(const char* path) {
|
||||
// nftw with FTW_DEPTH processes directory contents before the directory itself
|
||||
return nftw(path, remove_callback, 64, FTW_DEPTH | FTW_PHYS);
|
||||
}
|
||||
|
||||
#endif // LIBARCHIVE_FUZZ_HELPERS_H_
|
||||
63
contrib/oss-fuzz/libarchive_7zip_fuzzer.cc
Normal file
63
contrib/oss-fuzz/libarchive_7zip_fuzzer.cc
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 7-Zip format specific fuzzer for libarchive
|
||||
* Targets 7-Zip parsing and decompression code paths
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable 7-Zip format specifically
|
||||
archive_read_support_format_7zip(a);
|
||||
// Enable all filters for 7z internal compression
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Set passphrase for encrypted archives
|
||||
archive_read_add_passphrase(a, "password");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
// Exercise entry metadata access
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_is_encrypted(entry);
|
||||
archive_entry_is_data_encrypted(entry);
|
||||
archive_entry_is_metadata_encrypted(entry);
|
||||
|
||||
// Read data
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
47
contrib/oss-fuzz/libarchive_7zip_fuzzer.dict
Normal file
47
contrib/oss-fuzz/libarchive_7zip_fuzzer.dict
Normal file
@ -0,0 +1,47 @@
|
||||
# 7-Zip format dictionary
|
||||
# Magic bytes
|
||||
"7z\xbc\xaf\x27\x1c"
|
||||
"\x37\x7a\xbc\xaf\x27\x1c"
|
||||
|
||||
# Common property IDs
|
||||
"\x00"
|
||||
"\x01"
|
||||
"\x02"
|
||||
"\x03"
|
||||
"\x04"
|
||||
"\x05"
|
||||
"\x06"
|
||||
"\x07"
|
||||
"\x08"
|
||||
"\x09"
|
||||
"\x0a"
|
||||
"\x0b"
|
||||
"\x0c"
|
||||
"\x0d"
|
||||
"\x0e"
|
||||
"\x0f"
|
||||
"\x10"
|
||||
"\x11"
|
||||
"\x17"
|
||||
"\x19"
|
||||
"\x21"
|
||||
"\x23"
|
||||
"\x24"
|
||||
"\x25"
|
||||
|
||||
# Compression method IDs
|
||||
"\x00\x00"
|
||||
"\x00\x03"
|
||||
"\x00\x04"
|
||||
"\x00\x06"
|
||||
"\x01\x01"
|
||||
"\x03\x01\x01"
|
||||
"\x04\x01\x08"
|
||||
"\x04\x02\x02"
|
||||
"\x21\x01"
|
||||
"\x30\x01\x01"
|
||||
|
||||
# Encryption
|
||||
"\x06\xf1\x07\x01"
|
||||
"Password"
|
||||
"password"
|
||||
10
contrib/oss-fuzz/libarchive_7zip_fuzzer.options
Normal file
10
contrib/oss-fuzz/libarchive_7zip_fuzzer.options
Normal file
@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
54
contrib/oss-fuzz/libarchive_ar_fuzzer.cc
Normal file
54
contrib/oss-fuzz/libarchive_ar_fuzzer.cc
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* AR (Unix archive) format fuzzer for libarchive
|
||||
* Tests BSD and GNU ar formats
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_ar(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
20
contrib/oss-fuzz/libarchive_ar_fuzzer.dict
Normal file
20
contrib/oss-fuzz/libarchive_ar_fuzzer.dict
Normal file
@ -0,0 +1,20 @@
|
||||
# AR format dictionary
|
||||
|
||||
# AR magic
|
||||
"!<arch>\x0a"
|
||||
|
||||
# File header terminator
|
||||
"\x60\x0a"
|
||||
|
||||
# Special entries
|
||||
"/"
|
||||
"//"
|
||||
"/SYM64/"
|
||||
|
||||
# Common permissions
|
||||
"100644 "
|
||||
"100755 "
|
||||
|
||||
# UID/GID fields
|
||||
"0 "
|
||||
"1000 "
|
||||
51
contrib/oss-fuzz/libarchive_cab_fuzzer.cc
Normal file
51
contrib/oss-fuzz/libarchive_cab_fuzzer.cc
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* CAB (Microsoft Cabinet) format fuzzer for libarchive
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_cab(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
23
contrib/oss-fuzz/libarchive_cab_fuzzer.dict
Normal file
23
contrib/oss-fuzz/libarchive_cab_fuzzer.dict
Normal file
@ -0,0 +1,23 @@
|
||||
# CAB (Microsoft Cabinet) format dictionary
|
||||
|
||||
# CAB signature
|
||||
"MSCF"
|
||||
"\x4d\x53\x43\x46"
|
||||
|
||||
# Version
|
||||
"\x03\x01"
|
||||
|
||||
# Compression types
|
||||
"\x00\x00"
|
||||
"\x01\x00"
|
||||
"\x02\x00"
|
||||
"\x03\x00"
|
||||
|
||||
# Folder count patterns
|
||||
"\x01\x00"
|
||||
"\x02\x00"
|
||||
|
||||
# Header flags
|
||||
"\x00\x00"
|
||||
"\x01\x00"
|
||||
"\x04\x00"
|
||||
58
contrib/oss-fuzz/libarchive_cpio_fuzzer.cc
Normal file
58
contrib/oss-fuzz/libarchive_cpio_fuzzer.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* CPIO format fuzzer for libarchive
|
||||
* Tests all CPIO variants: binary, odc, newc, crc
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_cpio(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
archive_entry_ino(entry);
|
||||
archive_entry_nlink(entry);
|
||||
archive_entry_rdev(entry);
|
||||
archive_entry_hardlink(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
25
contrib/oss-fuzz/libarchive_cpio_fuzzer.dict
Normal file
25
contrib/oss-fuzz/libarchive_cpio_fuzzer.dict
Normal file
@ -0,0 +1,25 @@
|
||||
# CPIO format dictionary
|
||||
|
||||
# Binary magic (little endian)
|
||||
"\xc7\x71"
|
||||
|
||||
# Binary magic (big endian)
|
||||
"\x71\xc7"
|
||||
|
||||
# ASCII odc magic
|
||||
"070707"
|
||||
|
||||
# ASCII newc magic
|
||||
"070701"
|
||||
|
||||
# ASCII crc magic
|
||||
"070702"
|
||||
|
||||
# Common trailer
|
||||
"TRAILER!!!"
|
||||
|
||||
# Common field patterns
|
||||
"00000000"
|
||||
"00000001"
|
||||
"000001ed"
|
||||
"000003e8"
|
||||
101
contrib/oss-fuzz/libarchive_encryption_fuzzer.cc
Normal file
101
contrib/oss-fuzz/libarchive_encryption_fuzzer.cc
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Encrypted archive fuzzer for libarchive
|
||||
* Tests password/passphrase handling across formats
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
// Passphrase callback for testing
|
||||
static const char *test_passphrases[] = {
|
||||
"password",
|
||||
"test",
|
||||
"123456",
|
||||
"",
|
||||
"secret",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int passphrase_idx = 0;
|
||||
|
||||
static const char* passphrase_callback(struct archive *a, void *client_data) {
|
||||
(void)a;
|
||||
(void)client_data;
|
||||
const char *pass = test_passphrases[passphrase_idx];
|
||||
if (pass != NULL) {
|
||||
passphrase_idx++;
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reset passphrase index
|
||||
passphrase_idx = 0;
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable all formats that support encryption
|
||||
archive_read_support_format_zip(a);
|
||||
archive_read_support_format_7zip(a);
|
||||
archive_read_support_format_rar(a);
|
||||
archive_read_support_format_rar5(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Set up passphrase callback
|
||||
archive_read_set_passphrase_callback(a, NULL, passphrase_callback);
|
||||
|
||||
// Also add some static passphrases
|
||||
archive_read_add_passphrase(a, "password");
|
||||
archive_read_add_passphrase(a, "test123");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
int entry_count = 0;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK && entry_count < 100) {
|
||||
archive_entry_pathname(entry);
|
||||
|
||||
// Check encryption status
|
||||
int is_encrypted = archive_entry_is_encrypted(entry);
|
||||
int is_data_encrypted = archive_entry_is_data_encrypted(entry);
|
||||
int is_meta_encrypted = archive_entry_is_metadata_encrypted(entry);
|
||||
(void)is_encrypted;
|
||||
(void)is_data_encrypted;
|
||||
(void)is_meta_encrypted;
|
||||
|
||||
// Check if archive has encrypted entries
|
||||
archive_read_has_encrypted_entries(a);
|
||||
|
||||
// Try to read data (may fail due to wrong password)
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
10
contrib/oss-fuzz/libarchive_encryption_fuzzer.options
Normal file
10
contrib/oss-fuzz/libarchive_encryption_fuzzer.options
Normal file
@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
105
contrib/oss-fuzz/libarchive_entry_fuzzer.cc
Normal file
105
contrib/oss-fuzz/libarchive_entry_fuzzer.cc
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Archive entry fuzzer for libarchive
|
||||
* Targets archive_entry_* functions including ACL, linkify, and metadata
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 64 * 1024; // 64KB
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set basic entry properties
|
||||
archive_entry_set_pathname(entry, consumer.consume_string(256));
|
||||
archive_entry_set_size(entry, consumer.consume_i64());
|
||||
archive_entry_set_mode(entry, consumer.consume_u32());
|
||||
archive_entry_set_uid(entry, consumer.consume_u32());
|
||||
archive_entry_set_gid(entry, consumer.consume_u32());
|
||||
archive_entry_set_mtime(entry, consumer.consume_i64(), 0);
|
||||
archive_entry_set_atime(entry, consumer.consume_i64(), 0);
|
||||
archive_entry_set_ctime(entry, consumer.consume_i64(), 0);
|
||||
archive_entry_set_birthtime(entry, consumer.consume_i64(), 0);
|
||||
|
||||
// Set various string fields
|
||||
archive_entry_set_uname(entry, consumer.consume_string(64));
|
||||
archive_entry_set_gname(entry, consumer.consume_string(64));
|
||||
archive_entry_set_symlink(entry, consumer.consume_string(256));
|
||||
archive_entry_set_hardlink(entry, consumer.consume_string(256));
|
||||
|
||||
// Exercise ACL functions (low coverage targets)
|
||||
int acl_type = consumer.consume_byte() & 0x0F;
|
||||
int acl_permset = consumer.consume_u32();
|
||||
int acl_tag = consumer.consume_byte() & 0x0F;
|
||||
int acl_qual = consumer.consume_u32();
|
||||
const char *acl_name = consumer.consume_string(64);
|
||||
|
||||
archive_entry_acl_add_entry(entry, acl_type, acl_permset, acl_tag, acl_qual, acl_name);
|
||||
|
||||
// Add more ACL entries based on remaining data
|
||||
while (!consumer.empty() && consumer.remaining() > 10) {
|
||||
acl_type = consumer.consume_byte() & 0x0F;
|
||||
acl_permset = consumer.consume_u32();
|
||||
acl_tag = consumer.consume_byte() & 0x0F;
|
||||
acl_qual = consumer.consume_u32();
|
||||
acl_name = consumer.consume_string(32);
|
||||
archive_entry_acl_add_entry(entry, acl_type, acl_permset, acl_tag, acl_qual, acl_name);
|
||||
}
|
||||
|
||||
// Exercise ACL text conversion functions (archive_acl_to_text_* are uncovered)
|
||||
ssize_t text_len;
|
||||
char *acl_text = archive_entry_acl_to_text(entry, &text_len, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
if (acl_text) {
|
||||
// Parse the text back
|
||||
archive_entry_acl_from_text(entry, acl_text, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
free(acl_text);
|
||||
}
|
||||
|
||||
acl_text = archive_entry_acl_to_text(entry, &text_len, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
|
||||
if (acl_text) {
|
||||
free(acl_text);
|
||||
}
|
||||
|
||||
acl_text = archive_entry_acl_to_text(entry, &text_len, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
||||
if (acl_text) {
|
||||
free(acl_text);
|
||||
}
|
||||
|
||||
// Exercise wide character versions
|
||||
wchar_t *acl_text_w = archive_entry_acl_to_text_w(entry, &text_len, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
if (acl_text_w) {
|
||||
free(acl_text_w);
|
||||
}
|
||||
|
||||
// Get pathname variants
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_pathname_utf8(entry);
|
||||
|
||||
// Clone the entry
|
||||
struct archive_entry *entry2 = archive_entry_clone(entry);
|
||||
if (entry2) {
|
||||
archive_entry_free(entry2);
|
||||
}
|
||||
|
||||
// Clear and reuse
|
||||
archive_entry_clear(entry);
|
||||
|
||||
archive_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
65
contrib/oss-fuzz/libarchive_filter_fuzzer.cc
Normal file
65
contrib/oss-fuzz/libarchive_filter_fuzzer.cc
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Compression filter fuzzer for libarchive
|
||||
* Tests decompression of gzip, bzip2, xz, lzma, zstd, lz4, etc.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 256 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable raw format (just decompress, no archive format)
|
||||
archive_read_support_format_raw(a);
|
||||
|
||||
// Enable all compression filters
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(8192, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
if (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
// Get filter info
|
||||
int filter_count = archive_filter_count(a);
|
||||
for (int i = 0; i < filter_count; i++) {
|
||||
archive_filter_name(a, i);
|
||||
archive_filter_code(a, i);
|
||||
archive_filter_bytes(a, i);
|
||||
}
|
||||
|
||||
// Read all decompressed data
|
||||
ssize_t total = 0;
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0) {
|
||||
total += r;
|
||||
// Limit total decompressed size to prevent zip bombs
|
||||
if (total > 10 * 1024 * 1024) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
33
contrib/oss-fuzz/libarchive_filter_fuzzer.dict
Normal file
33
contrib/oss-fuzz/libarchive_filter_fuzzer.dict
Normal file
@ -0,0 +1,33 @@
|
||||
# Compression filter dictionary
|
||||
|
||||
# GZIP magic
|
||||
"\x1f\x8b"
|
||||
"\x1f\x8b\x08"
|
||||
|
||||
# BZIP2 magic
|
||||
"BZh"
|
||||
"BZ0"
|
||||
|
||||
# XZ magic
|
||||
"\xfd7zXZ\x00"
|
||||
|
||||
# LZMA magic
|
||||
"\x5d\x00\x00"
|
||||
|
||||
# ZSTD magic
|
||||
"\x28\xb5\x2f\xfd"
|
||||
|
||||
# LZ4 magic
|
||||
"\x04\x22\x4d\x18"
|
||||
|
||||
# Compress (.Z) magic
|
||||
"\x1f\x9d"
|
||||
|
||||
# LZIP magic
|
||||
"LZIP"
|
||||
|
||||
# LRZIP magic
|
||||
"LRZI"
|
||||
|
||||
# LZO magic
|
||||
"\x89LZO\x00\x0d\x0a\x1a\x0a"
|
||||
10
contrib/oss-fuzz/libarchive_filter_fuzzer.options
Normal file
10
contrib/oss-fuzz/libarchive_filter_fuzzer.options
Normal file
@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 262144
|
||||
timeout = 30
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 30
|
||||
|
||||
[afl]
|
||||
timeout = 30
|
||||
@ -3,20 +3,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
struct Buffer {
|
||||
const uint8_t *buf;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
ssize_t reader_callback(struct archive *a, void *client_data,
|
||||
const void **block) {
|
||||
Buffer *buffer = reinterpret_cast<Buffer *>(client_data);
|
||||
*block = buffer->buf;
|
||||
ssize_t len = buffer->len;
|
||||
buffer->len = 0;
|
||||
return len;
|
||||
}
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
int ret;
|
||||
@ -26,7 +13,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
archive_read_support_filter_all(a);
|
||||
archive_read_support_format_all(a);
|
||||
|
||||
Buffer buffer = {buf, len};
|
||||
Buffer buffer = {buf, len, 0};
|
||||
archive_read_open(a, &buffer, NULL, reader_callback, NULL);
|
||||
|
||||
std::vector<uint8_t> data_buffer(getpagesize(), 0);
|
||||
|
||||
76
contrib/oss-fuzz/libarchive_fuzzer.dict
Normal file
76
contrib/oss-fuzz/libarchive_fuzzer.dict
Normal file
@ -0,0 +1,76 @@
|
||||
# General libarchive dictionary covering multiple formats
|
||||
|
||||
# TAR magic
|
||||
"ustar"
|
||||
"ustar\x00"
|
||||
"ustar \x00"
|
||||
"\x00\x00"
|
||||
|
||||
# ZIP magic
|
||||
"PK\x03\x04"
|
||||
"PK\x05\x06"
|
||||
"PK\x01\x02"
|
||||
"PK\x07\x08"
|
||||
|
||||
# 7z magic
|
||||
"7z\xbc\xaf\x27\x1c"
|
||||
|
||||
# RAR magic
|
||||
"Rar!\x1a\x07\x00"
|
||||
"Rar!\x1a\x07\x01\x00"
|
||||
|
||||
# XAR magic
|
||||
"xar!"
|
||||
|
||||
# CPIO magic
|
||||
"\xc7\x71"
|
||||
"070701"
|
||||
"070702"
|
||||
"070707"
|
||||
|
||||
# CAB magic
|
||||
"MSCF"
|
||||
|
||||
# LHA magic
|
||||
"-lh"
|
||||
"-lz"
|
||||
|
||||
# AR magic
|
||||
"!<arch>\x0a"
|
||||
|
||||
# ISO9660 magic
|
||||
"CD001"
|
||||
|
||||
# GZIP magic
|
||||
"\x1f\x8b"
|
||||
|
||||
# BZIP2 magic
|
||||
"BZ"
|
||||
"BZh"
|
||||
|
||||
# XZ magic
|
||||
"\xfd7zXZ\x00"
|
||||
|
||||
# LZMA magic
|
||||
"\x5d\x00\x00"
|
||||
|
||||
# ZSTD magic
|
||||
"\x28\xb5\x2f\xfd"
|
||||
|
||||
# LZ4 magic
|
||||
"\x04\x22\x4d\x18"
|
||||
|
||||
# Common paths
|
||||
"/"
|
||||
"./"
|
||||
"../"
|
||||
"./test"
|
||||
"test.txt"
|
||||
"test/"
|
||||
|
||||
# Common attributes
|
||||
"\x00\x00\x00\x00"
|
||||
"\xff\xff\xff\xff"
|
||||
|
||||
# Passphrase
|
||||
"password"
|
||||
9
contrib/oss-fuzz/libarchive_fuzzer.options
Normal file
9
contrib/oss-fuzz/libarchive_fuzzer.options
Normal file
@ -0,0 +1,9 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 30
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 30
|
||||
|
||||
[afl]
|
||||
timeout = 30
|
||||
58
contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc
Normal file
58
contrib/oss-fuzz/libarchive_iso9660_fuzzer.cc
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* ISO9660 format fuzzer for libarchive
|
||||
* Tests ISO, Joliet, and Rock Ridge extensions
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 1024 * 1024; // 1MB for ISO images
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_iso9660(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Set options to test various ISO extensions
|
||||
archive_read_set_options(a, "iso9660:joliet,iso9660:rockridge");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_symlink(entry);
|
||||
archive_entry_hardlink(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
36
contrib/oss-fuzz/libarchive_iso9660_fuzzer.dict
Normal file
36
contrib/oss-fuzz/libarchive_iso9660_fuzzer.dict
Normal file
@ -0,0 +1,36 @@
|
||||
# ISO9660 format dictionary
|
||||
|
||||
# Volume descriptor type
|
||||
"\x00"
|
||||
"\x01"
|
||||
"\x02"
|
||||
"\xff"
|
||||
|
||||
# Standard identifier
|
||||
"CD001"
|
||||
|
||||
# Volume descriptor version
|
||||
"\x01"
|
||||
|
||||
# Joliet escape sequences
|
||||
"%/@"
|
||||
"%/C"
|
||||
"%/E"
|
||||
|
||||
# Rock Ridge signatures
|
||||
"SP"
|
||||
"RR"
|
||||
"CE"
|
||||
"PX"
|
||||
"PN"
|
||||
"SL"
|
||||
"NM"
|
||||
"CL"
|
||||
"PL"
|
||||
"RE"
|
||||
"TF"
|
||||
"SF"
|
||||
|
||||
# System use
|
||||
"ER"
|
||||
"ES"
|
||||
10
contrib/oss-fuzz/libarchive_iso9660_fuzzer.options
Normal file
10
contrib/oss-fuzz/libarchive_iso9660_fuzzer.options
Normal file
@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 1048576
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
54
contrib/oss-fuzz/libarchive_lha_fuzzer.cc
Normal file
54
contrib/oss-fuzz/libarchive_lha_fuzzer.cc
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* LHA/LZH format fuzzer for libarchive
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_lha(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
26
contrib/oss-fuzz/libarchive_lha_fuzzer.dict
Normal file
26
contrib/oss-fuzz/libarchive_lha_fuzzer.dict
Normal file
@ -0,0 +1,26 @@
|
||||
# LHA/LZH format dictionary
|
||||
|
||||
# Compression methods
|
||||
"-lh0-"
|
||||
"-lh1-"
|
||||
"-lh2-"
|
||||
"-lh3-"
|
||||
"-lh4-"
|
||||
"-lh5-"
|
||||
"-lh6-"
|
||||
"-lh7-"
|
||||
"-lhd-"
|
||||
"-lzs-"
|
||||
"-lz4-"
|
||||
"-lz5-"
|
||||
|
||||
# OS type
|
||||
"\x00"
|
||||
"\x4d"
|
||||
"\x55"
|
||||
|
||||
# Header levels
|
||||
"\x00"
|
||||
"\x01"
|
||||
"\x02"
|
||||
"\x03"
|
||||
110
contrib/oss-fuzz/libarchive_linkify_fuzzer.cc
Normal file
110
contrib/oss-fuzz/libarchive_linkify_fuzzer.cc
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Archive entry link resolver fuzzer for libarchive
|
||||
* Targets archive_entry_linkify (complexity: 775, zero coverage)
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 64 * 1024; // 64KB
|
||||
|
||||
// Simple data consumer
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
// Create a link resolver
|
||||
struct archive_entry_linkresolver *resolver = archive_entry_linkresolver_new();
|
||||
if (resolver == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set the format strategy based on input
|
||||
uint8_t strategy = consumer.consume_byte() % 5;
|
||||
int format;
|
||||
switch (strategy) {
|
||||
case 0: format = ARCHIVE_FORMAT_TAR_GNUTAR; break;
|
||||
case 1: format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE; break;
|
||||
case 2: format = ARCHIVE_FORMAT_CPIO_POSIX; break;
|
||||
case 3: format = ARCHIVE_FORMAT_CPIO_SVR4_NOCRC; break;
|
||||
default: format = ARCHIVE_FORMAT_TAR_USTAR; break;
|
||||
}
|
||||
archive_entry_linkresolver_set_strategy(resolver, format);
|
||||
|
||||
// Create multiple entries to test linkify with hardlinks
|
||||
struct archive_entry *entries[32];
|
||||
int num_entries = 0;
|
||||
|
||||
while (!consumer.empty() && num_entries < 32 && consumer.remaining() > 20) {
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) break;
|
||||
|
||||
// Set pathname
|
||||
archive_entry_set_pathname(entry, consumer.consume_string(64));
|
||||
|
||||
// Set inode and device for hardlink detection
|
||||
archive_entry_set_ino(entry, consumer.consume_i64());
|
||||
archive_entry_set_dev(entry, consumer.consume_u32());
|
||||
archive_entry_set_nlink(entry, (consumer.consume_byte() % 5) + 1);
|
||||
|
||||
// Set mode (regular file or directory)
|
||||
uint8_t ftype = consumer.consume_byte() % 2;
|
||||
mode_t mode = ftype ? (S_IFDIR | 0755) : (S_IFREG | 0644);
|
||||
archive_entry_set_mode(entry, mode);
|
||||
|
||||
archive_entry_set_size(entry, consumer.consume_i64() & 0xFFFF);
|
||||
archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
|
||||
entries[num_entries++] = entry;
|
||||
}
|
||||
|
||||
// Now run all entries through the linkresolver
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
struct archive_entry *entry = entries[i];
|
||||
struct archive_entry *spare = NULL;
|
||||
|
||||
// This is the main function we want to fuzz (zero coverage)
|
||||
archive_entry_linkify(resolver, &entry, &spare);
|
||||
|
||||
// entry and spare may be modified by linkify
|
||||
// We still need to free the original entries we allocated
|
||||
if (spare != NULL) {
|
||||
archive_entry_free(spare);
|
||||
}
|
||||
}
|
||||
|
||||
// Free remaining entries from the resolver
|
||||
struct archive_entry *entry = NULL;
|
||||
struct archive_entry *spare = NULL;
|
||||
while (1) {
|
||||
archive_entry_linkify(resolver, &entry, &spare);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
archive_entry_free(entry);
|
||||
entry = NULL;
|
||||
if (spare != NULL) {
|
||||
archive_entry_free(spare);
|
||||
spare = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Free all our created entries
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
if (entries[i] != NULL) {
|
||||
archive_entry_free(entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
archive_entry_linkresolver_free(resolver);
|
||||
return 0;
|
||||
}
|
||||
96
contrib/oss-fuzz/libarchive_match_fuzzer.cc
Normal file
96
contrib/oss-fuzz/libarchive_match_fuzzer.cc
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Archive match fuzzer for libarchive
|
||||
* Tests pattern matching, time matching, and owner matching
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 32 * 1024;
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
struct archive *match = archive_match_new();
|
||||
if (match == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add various match patterns
|
||||
while (!consumer.empty() && consumer.remaining() > 5) {
|
||||
uint8_t match_type = consumer.consume_byte() % 6;
|
||||
|
||||
switch (match_type) {
|
||||
case 0: {
|
||||
// Pattern exclusion
|
||||
const char *pattern = consumer.consume_string(64);
|
||||
archive_match_exclude_pattern(match, pattern);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
// Pattern inclusion
|
||||
const char *pattern = consumer.consume_string(64);
|
||||
archive_match_include_pattern(match, pattern);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// Time comparison (newer than)
|
||||
int64_t sec = consumer.consume_i64();
|
||||
int64_t nsec = consumer.consume_i64() % 1000000000;
|
||||
archive_match_include_time(match, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_NEWER,
|
||||
sec, nsec);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// Time comparison (older than)
|
||||
int64_t sec = consumer.consume_i64();
|
||||
int64_t nsec = consumer.consume_i64() % 1000000000;
|
||||
archive_match_include_time(match, ARCHIVE_MATCH_MTIME | ARCHIVE_MATCH_OLDER,
|
||||
sec, nsec);
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
// UID inclusion
|
||||
int64_t uid = consumer.consume_i64() & 0xFFFF;
|
||||
archive_match_include_uid(match, uid);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
// GID inclusion
|
||||
int64_t gid = consumer.consume_i64() & 0xFFFF;
|
||||
archive_match_include_gid(match, gid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create a test entry and check if it matches
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry) {
|
||||
archive_entry_set_pathname(entry, "test/file.txt");
|
||||
archive_entry_set_mtime(entry, 1234567890, 0);
|
||||
archive_entry_set_uid(entry, 1000);
|
||||
archive_entry_set_gid(entry, 1000);
|
||||
archive_entry_set_mode(entry, 0644 | 0100000); // Regular file
|
||||
|
||||
// Test matching
|
||||
archive_match_path_excluded(match, entry);
|
||||
archive_match_time_excluded(match, entry);
|
||||
archive_match_owner_excluded(match, entry);
|
||||
archive_match_excluded(match, entry);
|
||||
|
||||
archive_entry_free(entry);
|
||||
}
|
||||
|
||||
archive_match_free(match);
|
||||
return 0;
|
||||
}
|
||||
61
contrib/oss-fuzz/libarchive_mtree_fuzzer.cc
Normal file
61
contrib/oss-fuzz/libarchive_mtree_fuzzer.cc
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* MTREE format fuzzer for libarchive
|
||||
* Tests mtree manifest parsing
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 256 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_mtree(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Enable checkfs option to test more code paths
|
||||
archive_read_set_options(a, "mtree:checkfs");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
archive_entry_uname(entry);
|
||||
archive_entry_gname(entry);
|
||||
archive_entry_symlink(entry);
|
||||
archive_entry_fflags_text(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
47
contrib/oss-fuzz/libarchive_mtree_fuzzer.dict
Normal file
47
contrib/oss-fuzz/libarchive_mtree_fuzzer.dict
Normal file
@ -0,0 +1,47 @@
|
||||
# MTREE format dictionary
|
||||
|
||||
# Keywords
|
||||
"/set"
|
||||
"/unset"
|
||||
".."
|
||||
|
||||
# File types
|
||||
"type=file"
|
||||
"type=dir"
|
||||
"type=link"
|
||||
"type=block"
|
||||
"type=char"
|
||||
"type=fifo"
|
||||
"type=socket"
|
||||
|
||||
# Attributes
|
||||
"mode="
|
||||
"uid="
|
||||
"gid="
|
||||
"uname="
|
||||
"gname="
|
||||
"size="
|
||||
"time="
|
||||
"link="
|
||||
"cksum="
|
||||
"md5="
|
||||
"md5digest="
|
||||
"sha1="
|
||||
"sha1digest="
|
||||
"sha256="
|
||||
"sha256digest="
|
||||
"sha384="
|
||||
"sha384digest="
|
||||
"sha512="
|
||||
"sha512digest="
|
||||
"rmd160="
|
||||
"rmd160digest="
|
||||
"flags="
|
||||
"nlink="
|
||||
"inode="
|
||||
"device="
|
||||
"resdevice="
|
||||
"contents="
|
||||
"optional"
|
||||
"ignore"
|
||||
"nochange"
|
||||
61
contrib/oss-fuzz/libarchive_rar5_fuzzer.cc
Normal file
61
contrib/oss-fuzz/libarchive_rar5_fuzzer.cc
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* RAR5 format specific fuzzer for libarchive
|
||||
* Targets RAR5 parsing code paths
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable RAR5 format specifically
|
||||
archive_read_support_format_rar5(a);
|
||||
// Enable common filters
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Set passphrase for encrypted archives
|
||||
archive_read_add_passphrase(a, "password");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
// Exercise entry metadata access
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_is_encrypted(entry);
|
||||
|
||||
// Read data
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
37
contrib/oss-fuzz/libarchive_rar5_fuzzer.dict
Normal file
37
contrib/oss-fuzz/libarchive_rar5_fuzzer.dict
Normal file
@ -0,0 +1,37 @@
|
||||
# RAR5 format dictionary
|
||||
# Magic bytes (RAR5 signature)
|
||||
"Rar!\x1a\x07\x01\x00"
|
||||
"\x52\x61\x72\x21\x1a\x07\x01\x00"
|
||||
|
||||
# Common header types
|
||||
"\x01"
|
||||
"\x02"
|
||||
"\x03"
|
||||
"\x04"
|
||||
"\x05"
|
||||
|
||||
# Common flags
|
||||
"\x00\x00"
|
||||
"\x01\x00"
|
||||
"\x02\x00"
|
||||
"\x04\x00"
|
||||
|
||||
# Compression methods
|
||||
"\x00"
|
||||
"\x01"
|
||||
"\x02"
|
||||
"\x03"
|
||||
"\x04"
|
||||
"\x05"
|
||||
|
||||
# File attributes
|
||||
"\x20\x00\x00\x00"
|
||||
"\x10\x00\x00\x00"
|
||||
|
||||
# Encryption marker
|
||||
"\x80"
|
||||
"password"
|
||||
"Password"
|
||||
|
||||
# End of archive
|
||||
"\x1d\x77\x56\x51\x03\x05\x04\x00"
|
||||
56
contrib/oss-fuzz/libarchive_rar_fuzzer.cc
Normal file
56
contrib/oss-fuzz/libarchive_rar_fuzzer.cc
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* RAR v4 format fuzzer for libarchive
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_rar(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Add passphrase for encrypted RARs
|
||||
archive_read_add_passphrase(a, "password");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_is_encrypted(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
76
contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc
Normal file
76
contrib/oss-fuzz/libarchive_read_disk_fuzzer.cc
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Archive read disk fuzzer for libarchive
|
||||
* Tests filesystem traversal and entry creation from paths
|
||||
* Security-critical: path traversal, symlink handling
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 16 * 1024;
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
struct archive *a = archive_read_disk_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Configure disk reader behavior
|
||||
uint8_t flags = consumer.consume_byte();
|
||||
if (flags & 0x01) {
|
||||
archive_read_disk_set_symlink_logical(a);
|
||||
} else if (flags & 0x02) {
|
||||
archive_read_disk_set_symlink_physical(a);
|
||||
} else {
|
||||
archive_read_disk_set_symlink_hybrid(a);
|
||||
}
|
||||
|
||||
archive_read_disk_set_standard_lookup(a);
|
||||
|
||||
// Set behavior flags
|
||||
int behavior = 0;
|
||||
if (flags & 0x04) behavior |= ARCHIVE_READDISK_RESTORE_ATIME;
|
||||
if (flags & 0x08) behavior |= ARCHIVE_READDISK_HONOR_NODUMP;
|
||||
if (flags & 0x10) behavior |= ARCHIVE_READDISK_NO_TRAVERSE_MOUNTS;
|
||||
archive_read_disk_set_behavior(a, behavior);
|
||||
|
||||
// Create an entry and test entry_from_file with various paths
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry) {
|
||||
// Test with /tmp (safe, always exists)
|
||||
archive_entry_copy_pathname(entry, "/tmp");
|
||||
archive_read_disk_entry_from_file(a, entry, -1, NULL);
|
||||
|
||||
// Get entry info
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
|
||||
// Test name lookups
|
||||
archive_read_disk_gname(a, 0);
|
||||
archive_read_disk_uname(a, 0);
|
||||
archive_read_disk_gname(a, 1000);
|
||||
archive_read_disk_uname(a, 1000);
|
||||
|
||||
archive_entry_free(entry);
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
110
contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc
Normal file
110
contrib/oss-fuzz/libarchive_roundtrip_fuzzer.cc
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Archive roundtrip fuzzer for libarchive
|
||||
* Writes an archive then reads it back - tests write/read consistency
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 64 * 1024;
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len < 10 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
std::vector<uint8_t> archive_data;
|
||||
archive_data.reserve(len * 2);
|
||||
|
||||
// Phase 1: Write an archive
|
||||
struct archive *writer = archive_write_new();
|
||||
if (writer == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Select format
|
||||
uint8_t format = consumer.consume_byte() % 5;
|
||||
switch (format) {
|
||||
case 0: archive_write_set_format_pax_restricted(writer); break;
|
||||
case 1: archive_write_set_format_ustar(writer); break;
|
||||
case 2: archive_write_set_format_cpio_newc(writer); break;
|
||||
case 3: archive_write_set_format_zip(writer); break;
|
||||
default: archive_write_set_format_gnutar(writer); break;
|
||||
}
|
||||
|
||||
archive_write_add_filter_none(writer);
|
||||
|
||||
// Open to memory
|
||||
size_t used = 0;
|
||||
archive_data.resize(len * 4);
|
||||
if (archive_write_open_memory(writer, archive_data.data(), archive_data.size(), &used) != ARCHIVE_OK) {
|
||||
archive_write_free(writer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write entries
|
||||
int entry_count = 0;
|
||||
while (!consumer.empty() && entry_count < 5 && consumer.remaining() > 10) {
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) break;
|
||||
|
||||
archive_entry_set_pathname(entry, consumer.consume_string(32));
|
||||
archive_entry_set_mode(entry, S_IFREG | 0644);
|
||||
archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
|
||||
uint8_t data_buf[256];
|
||||
size_t data_len = consumer.consume_bytes(data_buf, 256);
|
||||
archive_entry_set_size(entry, data_len);
|
||||
|
||||
if (archive_write_header(writer, entry) == ARCHIVE_OK && data_len > 0) {
|
||||
archive_write_data(writer, data_buf, data_len);
|
||||
}
|
||||
|
||||
archive_entry_free(entry);
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
archive_write_close(writer);
|
||||
archive_write_free(writer);
|
||||
|
||||
if (used == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Phase 2: Read the archive back
|
||||
struct archive *reader = archive_read_new();
|
||||
if (reader == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_all(reader);
|
||||
archive_read_support_filter_all(reader);
|
||||
|
||||
if (archive_read_open_memory(reader, archive_data.data(), used) != ARCHIVE_OK) {
|
||||
archive_read_free(reader);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
while (archive_read_next_header(reader, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(reader, read_buffer.data(), read_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(reader);
|
||||
return 0;
|
||||
}
|
||||
3
contrib/oss-fuzz/libarchive_roundtrip_fuzzer.options
Normal file
3
contrib/oss-fuzz/libarchive_roundtrip_fuzzer.options
Normal file
@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 65536
|
||||
timeout = 30
|
||||
125
contrib/oss-fuzz/libarchive_seek_fuzzer.cc
Normal file
125
contrib/oss-fuzz/libarchive_seek_fuzzer.cc
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Archive seek/read fuzzer for libarchive
|
||||
* Tests seeking within archives and reading at random positions
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 256 * 1024;
|
||||
|
||||
struct SeekableBuffer {
|
||||
const uint8_t *buf;
|
||||
size_t len;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
static ssize_t seek_read_callback(struct archive *a, void *client_data,
|
||||
const void **block) {
|
||||
(void)a;
|
||||
SeekableBuffer *buffer = reinterpret_cast<SeekableBuffer *>(client_data);
|
||||
if (buffer->pos >= buffer->len) {
|
||||
*block = NULL;
|
||||
return 0;
|
||||
}
|
||||
*block = buffer->buf + buffer->pos;
|
||||
size_t avail = buffer->len - buffer->pos;
|
||||
size_t to_read = (avail > 4096) ? 4096 : avail;
|
||||
buffer->pos += to_read;
|
||||
return to_read;
|
||||
}
|
||||
|
||||
static la_int64_t seek_callback(struct archive *a, void *client_data,
|
||||
la_int64_t offset, int whence) {
|
||||
(void)a;
|
||||
SeekableBuffer *buffer = reinterpret_cast<SeekableBuffer *>(client_data);
|
||||
la_int64_t new_pos;
|
||||
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
new_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
new_pos = static_cast<la_int64_t>(buffer->pos) + offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
new_pos = static_cast<la_int64_t>(buffer->len) + offset;
|
||||
break;
|
||||
default:
|
||||
return ARCHIVE_FATAL;
|
||||
}
|
||||
|
||||
if (new_pos < 0) new_pos = 0;
|
||||
if (new_pos > static_cast<la_int64_t>(buffer->len))
|
||||
new_pos = static_cast<la_int64_t>(buffer->len);
|
||||
|
||||
buffer->pos = static_cast<size_t>(new_pos);
|
||||
return new_pos;
|
||||
}
|
||||
|
||||
static la_int64_t skip_callback(struct archive *a, void *client_data,
|
||||
la_int64_t request) {
|
||||
(void)a;
|
||||
SeekableBuffer *buffer = reinterpret_cast<SeekableBuffer *>(client_data);
|
||||
size_t avail = buffer->len - buffer->pos;
|
||||
la_int64_t to_skip = (request > static_cast<la_int64_t>(avail))
|
||||
? static_cast<la_int64_t>(avail)
|
||||
: request;
|
||||
buffer->pos += static_cast<size_t>(to_skip);
|
||||
return to_skip;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable formats that benefit from seeking
|
||||
archive_read_support_format_zip_seekable(a);
|
||||
archive_read_support_format_7zip(a);
|
||||
archive_read_support_format_rar(a);
|
||||
archive_read_support_format_rar5(a);
|
||||
archive_read_support_format_iso9660(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
SeekableBuffer buffer = {buf, len, 0};
|
||||
|
||||
archive_read_set_read_callback(a, seek_read_callback);
|
||||
archive_read_set_seek_callback(a, seek_callback);
|
||||
archive_read_set_skip_callback(a, skip_callback);
|
||||
archive_read_set_callback_data(a, &buffer);
|
||||
|
||||
if (archive_read_open1(a) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
int entry_count = 0;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK && entry_count < 50) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
|
||||
// Read data which may trigger seeks
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
3
contrib/oss-fuzz/libarchive_seek_fuzzer.options
Normal file
3
contrib/oss-fuzz/libarchive_seek_fuzzer.options
Normal file
@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 262144
|
||||
timeout = 30
|
||||
144
contrib/oss-fuzz/libarchive_string_fuzzer.cc
Normal file
144
contrib/oss-fuzz/libarchive_string_fuzzer.cc
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Archive string/encoding conversion fuzzer for libarchive
|
||||
* Tests character encoding conversions which are often vulnerability sources
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 32 * 1024;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reserve some bytes for control
|
||||
if (len < 4) {
|
||||
archive_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t test_type = buf[0];
|
||||
const char *str = reinterpret_cast<const char*>(buf + 1);
|
||||
size_t str_len = len - 1;
|
||||
|
||||
// Ensure null termination for string operations
|
||||
char *safe_str = static_cast<char*>(malloc(str_len + 1));
|
||||
if (safe_str == NULL) {
|
||||
archive_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
memcpy(safe_str, str, str_len);
|
||||
safe_str[str_len] = '\0';
|
||||
|
||||
// Test various string functions based on type
|
||||
switch (test_type % 10) {
|
||||
case 0:
|
||||
// Pathname conversions
|
||||
archive_entry_set_pathname(entry, safe_str);
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_pathname_utf8(entry);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Symlink conversions
|
||||
archive_entry_set_symlink(entry, safe_str);
|
||||
archive_entry_symlink(entry);
|
||||
archive_entry_symlink_w(entry);
|
||||
archive_entry_symlink_utf8(entry);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// Hardlink conversions
|
||||
archive_entry_set_hardlink(entry, safe_str);
|
||||
archive_entry_hardlink(entry);
|
||||
archive_entry_hardlink_w(entry);
|
||||
archive_entry_hardlink_utf8(entry);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Username conversions
|
||||
archive_entry_set_uname(entry, safe_str);
|
||||
archive_entry_uname(entry);
|
||||
archive_entry_uname_w(entry);
|
||||
archive_entry_uname_utf8(entry);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// Group name conversions
|
||||
archive_entry_set_gname(entry, safe_str);
|
||||
archive_entry_gname(entry);
|
||||
archive_entry_gname_w(entry);
|
||||
archive_entry_gname_utf8(entry);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// Copy functions
|
||||
archive_entry_copy_pathname(entry, safe_str);
|
||||
archive_entry_copy_symlink(entry, safe_str);
|
||||
archive_entry_copy_hardlink(entry, safe_str);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
// UTF-8 specific
|
||||
archive_entry_update_pathname_utf8(entry, safe_str);
|
||||
archive_entry_update_symlink_utf8(entry, safe_str);
|
||||
archive_entry_update_hardlink_utf8(entry, safe_str);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
// Fflags text
|
||||
archive_entry_copy_fflags_text(entry, safe_str);
|
||||
archive_entry_fflags_text(entry);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
// ACL text parsing
|
||||
archive_entry_acl_from_text(entry, safe_str, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
|
||||
archive_entry_acl_from_text(entry, safe_str, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
|
||||
archive_entry_acl_from_text(entry, safe_str, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
|
||||
break;
|
||||
|
||||
case 9: {
|
||||
// Wide character operations
|
||||
size_t wlen = str_len;
|
||||
wchar_t *wstr = static_cast<wchar_t*>(malloc((wlen + 1) * sizeof(wchar_t)));
|
||||
if (wstr) {
|
||||
mbstowcs(wstr, safe_str, wlen);
|
||||
wstr[wlen] = L'\0';
|
||||
|
||||
archive_entry_copy_pathname_w(entry, wstr);
|
||||
archive_entry_pathname_w(entry);
|
||||
|
||||
archive_entry_copy_symlink_w(entry, wstr);
|
||||
archive_entry_symlink_w(entry);
|
||||
|
||||
free(wstr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clone and compare
|
||||
struct archive_entry *entry2 = archive_entry_clone(entry);
|
||||
if (entry2) {
|
||||
archive_entry_free(entry2);
|
||||
}
|
||||
|
||||
free(safe_str);
|
||||
archive_entry_free(entry);
|
||||
return 0;
|
||||
}
|
||||
86
contrib/oss-fuzz/libarchive_tar_fuzzer.cc
Normal file
86
contrib/oss-fuzz/libarchive_tar_fuzzer.cc
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* TAR format fuzzer for libarchive
|
||||
* Tests all TAR variants: ustar, pax, gnutar, v7, oldgnu
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_tar(a);
|
||||
archive_read_support_format_gnutar(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Enable various TAR options
|
||||
archive_read_set_options(a, "tar:read_concatenated_archives,tar:mac-ext");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
// Exercise all metadata accessors
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_atime(entry);
|
||||
archive_entry_ctime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
archive_entry_uname(entry);
|
||||
archive_entry_gname(entry);
|
||||
archive_entry_symlink(entry);
|
||||
archive_entry_hardlink(entry);
|
||||
archive_entry_rdev(entry);
|
||||
archive_entry_devmajor(entry);
|
||||
archive_entry_devminor(entry);
|
||||
|
||||
// Test sparse file handling
|
||||
archive_entry_sparse_reset(entry);
|
||||
int64_t offset, length;
|
||||
while (archive_entry_sparse_next(entry, &offset, &length) == ARCHIVE_OK) {
|
||||
(void)offset;
|
||||
(void)length;
|
||||
}
|
||||
|
||||
// Test xattr handling
|
||||
archive_entry_xattr_reset(entry);
|
||||
const char *name;
|
||||
const void *value;
|
||||
size_t size;
|
||||
while (archive_entry_xattr_next(entry, &name, &value, &size) == ARCHIVE_OK) {
|
||||
(void)name;
|
||||
(void)value;
|
||||
(void)size;
|
||||
}
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
51
contrib/oss-fuzz/libarchive_tar_fuzzer.dict
Normal file
51
contrib/oss-fuzz/libarchive_tar_fuzzer.dict
Normal file
@ -0,0 +1,51 @@
|
||||
# TAR format dictionary
|
||||
|
||||
# USTAR magic
|
||||
"ustar"
|
||||
"ustar\x00"
|
||||
"ustar \x00"
|
||||
|
||||
# GNU tar magic
|
||||
"GNUtar "
|
||||
"GNUtar\x00"
|
||||
|
||||
# Common header field values
|
||||
"00000000000"
|
||||
"0000644"
|
||||
"0000755"
|
||||
"0000777"
|
||||
|
||||
# Type flags
|
||||
"0"
|
||||
"1"
|
||||
"2"
|
||||
"3"
|
||||
"4"
|
||||
"5"
|
||||
"6"
|
||||
"7"
|
||||
"g"
|
||||
"x"
|
||||
"L"
|
||||
"K"
|
||||
|
||||
# PAX keywords
|
||||
"path="
|
||||
"linkpath="
|
||||
"uname="
|
||||
"gname="
|
||||
"uid="
|
||||
"gid="
|
||||
"size="
|
||||
"mtime="
|
||||
"atime="
|
||||
"ctime="
|
||||
"SCHILY.xattr."
|
||||
"LIBARCHIVE.xattr."
|
||||
|
||||
# Sparse headers
|
||||
"GNU.sparse.major="
|
||||
"GNU.sparse.minor="
|
||||
"GNU.sparse.name="
|
||||
"GNU.sparse.realsize="
|
||||
"GNU.sparse.map="
|
||||
50
contrib/oss-fuzz/libarchive_warc_fuzzer.cc
Normal file
50
contrib/oss-fuzz/libarchive_warc_fuzzer.cc
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* WARC (Web Archive) format fuzzer for libarchive
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_warc(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
34
contrib/oss-fuzz/libarchive_warc_fuzzer.dict
Normal file
34
contrib/oss-fuzz/libarchive_warc_fuzzer.dict
Normal file
@ -0,0 +1,34 @@
|
||||
# WARC format dictionary
|
||||
|
||||
# Version
|
||||
"WARC/1.0"
|
||||
"WARC/1.1"
|
||||
"WARC/0.17"
|
||||
"WARC/0.18"
|
||||
|
||||
# Record types
|
||||
"warcinfo"
|
||||
"response"
|
||||
"resource"
|
||||
"request"
|
||||
"metadata"
|
||||
"revisit"
|
||||
"conversion"
|
||||
"continuation"
|
||||
|
||||
# Headers
|
||||
"WARC-Type:"
|
||||
"WARC-Record-ID:"
|
||||
"WARC-Date:"
|
||||
"WARC-Target-URI:"
|
||||
"Content-Length:"
|
||||
"Content-Type:"
|
||||
"WARC-Block-Digest:"
|
||||
"WARC-Payload-Digest:"
|
||||
"WARC-Concurrent-To:"
|
||||
"WARC-Refers-To:"
|
||||
|
||||
# Content types
|
||||
"application/warc-fields"
|
||||
"application/http;msgtype=request"
|
||||
"application/http;msgtype=response"
|
||||
125
contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc
Normal file
125
contrib/oss-fuzz/libarchive_write_disk_fuzzer.cc
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Archive write disk fuzzer for libarchive
|
||||
* Tests extraction to filesystem
|
||||
* Security-critical: path traversal, permission handling, symlink attacks
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 64 * 1024;
|
||||
|
||||
static char g_temp_dir[256] = {0};
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
// Create a temporary directory for extraction
|
||||
snprintf(g_temp_dir, sizeof(g_temp_dir), "/tmp/fuzz_extract_XXXXXX");
|
||||
if (mkdtemp(g_temp_dir) == NULL) {
|
||||
g_temp_dir[0] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_temp_dir[0] == '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
struct archive *disk = archive_write_disk_new();
|
||||
if (disk == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Configure write disk options
|
||||
uint8_t opt_flags = consumer.consume_byte();
|
||||
int flags = 0;
|
||||
if (opt_flags & 0x01) flags |= ARCHIVE_EXTRACT_TIME;
|
||||
if (opt_flags & 0x02) flags |= ARCHIVE_EXTRACT_PERM;
|
||||
if (opt_flags & 0x04) flags |= ARCHIVE_EXTRACT_ACL;
|
||||
if (opt_flags & 0x08) flags |= ARCHIVE_EXTRACT_FFLAGS;
|
||||
if (opt_flags & 0x10) flags |= ARCHIVE_EXTRACT_OWNER;
|
||||
if (opt_flags & 0x20) flags |= ARCHIVE_EXTRACT_XATTR;
|
||||
if (opt_flags & 0x40) flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS;
|
||||
if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
|
||||
|
||||
archive_write_disk_set_options(disk, flags);
|
||||
archive_write_disk_set_standard_lookup(disk);
|
||||
|
||||
// Create entries to extract
|
||||
int entry_count = 0;
|
||||
while (!consumer.empty() && entry_count < 5 && consumer.remaining() > 20) {
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) break;
|
||||
|
||||
// Build a safe path within our temp directory
|
||||
char safe_path[512];
|
||||
const char *name = consumer.consume_string(32);
|
||||
snprintf(safe_path, sizeof(safe_path), "%s/%s", g_temp_dir, name);
|
||||
|
||||
// Sanitize path to prevent traversal
|
||||
char *p = safe_path;
|
||||
while (*p) {
|
||||
if (p[0] == '.' && p[1] == '.') {
|
||||
p[0] = '_';
|
||||
p[1] = '_';
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
archive_entry_set_pathname(entry, safe_path);
|
||||
|
||||
uint8_t ftype = consumer.consume_byte() % 3;
|
||||
mode_t mode;
|
||||
switch (ftype) {
|
||||
case 0: mode = S_IFREG | 0644; break;
|
||||
case 1: mode = S_IFDIR | 0755; break;
|
||||
default: mode = S_IFREG | 0644; break;
|
||||
}
|
||||
archive_entry_set_mode(entry, mode);
|
||||
|
||||
archive_entry_set_uid(entry, 1000);
|
||||
archive_entry_set_gid(entry, 1000);
|
||||
archive_entry_set_mtime(entry, consumer.consume_i64(), 0);
|
||||
|
||||
// Write the entry header
|
||||
if (archive_write_header(disk, entry) == ARCHIVE_OK) {
|
||||
if (S_ISREG(mode)) {
|
||||
uint8_t data_buf[256];
|
||||
size_t data_len = consumer.consume_bytes(data_buf, 256);
|
||||
archive_entry_set_size(entry, data_len);
|
||||
if (data_len > 0) {
|
||||
archive_write_data(disk, data_buf, data_len);
|
||||
}
|
||||
}
|
||||
archive_write_finish_entry(disk);
|
||||
}
|
||||
|
||||
archive_entry_free(entry);
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
archive_write_close(disk);
|
||||
archive_write_free(disk);
|
||||
|
||||
// Clean up extracted files using nftw (safer than system())
|
||||
remove_directory_tree(g_temp_dir);
|
||||
// Recreate the temp directory for next iteration
|
||||
mkdir(g_temp_dir, 0700);
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
contrib/oss-fuzz/libarchive_write_disk_fuzzer.options
Normal file
3
contrib/oss-fuzz/libarchive_write_disk_fuzzer.options
Normal file
@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 65536
|
||||
timeout = 30
|
||||
132
contrib/oss-fuzz/libarchive_write_fuzzer.cc
Normal file
132
contrib/oss-fuzz/libarchive_write_fuzzer.cc
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Archive write fuzzer for libarchive
|
||||
* Tests archive creation and writing code paths
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 64 * 1024; // 64KB
|
||||
|
||||
// Simple data consumer
|
||||
|
||||
// Memory write callback
|
||||
static std::vector<uint8_t> *g_output = nullptr;
|
||||
|
||||
static ssize_t write_callback(struct archive *a, void *client_data, const void *buffer, size_t length) {
|
||||
(void)a;
|
||||
(void)client_data;
|
||||
if (g_output && length > 0) {
|
||||
const uint8_t *buf = static_cast<const uint8_t*>(buffer);
|
||||
g_output->insert(g_output->end(), buf, buf + length);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static int close_callback(struct archive *a, void *client_data) {
|
||||
(void)a;
|
||||
(void)client_data;
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
std::vector<uint8_t> output;
|
||||
g_output = &output;
|
||||
|
||||
struct archive *a = archive_write_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Select format based on input
|
||||
uint8_t format_choice = consumer.consume_byte() % 8;
|
||||
switch (format_choice) {
|
||||
case 0: archive_write_set_format_pax_restricted(a); break;
|
||||
case 1: archive_write_set_format_gnutar(a); break;
|
||||
case 2: archive_write_set_format_ustar(a); break;
|
||||
case 3: archive_write_set_format_cpio_newc(a); break;
|
||||
case 4: archive_write_set_format_zip(a); break;
|
||||
case 5: archive_write_set_format_7zip(a); break;
|
||||
case 6: archive_write_set_format_xar(a); break;
|
||||
default: archive_write_set_format_pax(a); break;
|
||||
}
|
||||
|
||||
// Select compression based on input
|
||||
uint8_t filter_choice = consumer.consume_byte() % 6;
|
||||
switch (filter_choice) {
|
||||
case 0: archive_write_add_filter_gzip(a); break;
|
||||
case 1: archive_write_add_filter_bzip2(a); break;
|
||||
case 2: archive_write_add_filter_xz(a); break;
|
||||
case 3: archive_write_add_filter_zstd(a); break;
|
||||
case 4: archive_write_add_filter_none(a); break;
|
||||
default: archive_write_add_filter_none(a); break;
|
||||
}
|
||||
|
||||
// Open for writing to memory
|
||||
if (archive_write_open(a, NULL, NULL, write_callback, close_callback) != ARCHIVE_OK) {
|
||||
archive_write_free(a);
|
||||
g_output = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create entries based on remaining input
|
||||
int entry_count = 0;
|
||||
while (!consumer.empty() && entry_count < 10 && consumer.remaining() > 20) {
|
||||
struct archive_entry *entry = archive_entry_new();
|
||||
if (entry == NULL) break;
|
||||
|
||||
// Set entry properties
|
||||
archive_entry_set_pathname(entry, consumer.consume_string(64));
|
||||
|
||||
uint8_t ftype = consumer.consume_byte() % 4;
|
||||
mode_t mode;
|
||||
switch (ftype) {
|
||||
case 0: mode = S_IFREG | 0644; break;
|
||||
case 1: mode = S_IFDIR | 0755; break;
|
||||
case 2: mode = S_IFLNK | 0777; break;
|
||||
default: mode = S_IFREG | 0644; break;
|
||||
}
|
||||
archive_entry_set_mode(entry, mode);
|
||||
|
||||
archive_entry_set_uid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
archive_entry_set_gid(entry, consumer.consume_u32() & 0xFFFF);
|
||||
archive_entry_set_mtime(entry, consumer.consume_i64(), 0);
|
||||
|
||||
// For regular files, write some data
|
||||
if (S_ISREG(mode)) {
|
||||
uint8_t data_buf[1024];
|
||||
size_t data_len = consumer.consume_bytes(data_buf, 1024);
|
||||
archive_entry_set_size(entry, data_len);
|
||||
|
||||
if (archive_write_header(a, entry) == ARCHIVE_OK && data_len > 0) {
|
||||
archive_write_data(a, data_buf, data_len);
|
||||
}
|
||||
} else if (S_ISLNK(mode)) {
|
||||
archive_entry_set_symlink(entry, consumer.consume_string(64));
|
||||
archive_entry_set_size(entry, 0);
|
||||
archive_write_header(a, entry);
|
||||
} else {
|
||||
archive_entry_set_size(entry, 0);
|
||||
archive_write_header(a, entry);
|
||||
}
|
||||
|
||||
archive_entry_free(entry);
|
||||
entry_count++;
|
||||
}
|
||||
|
||||
archive_write_close(a);
|
||||
archive_write_free(a);
|
||||
g_output = nullptr;
|
||||
return 0;
|
||||
}
|
||||
60
contrib/oss-fuzz/libarchive_xar_fuzzer.cc
Normal file
60
contrib/oss-fuzz/libarchive_xar_fuzzer.cc
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* XAR format specific fuzzer for libarchive
|
||||
* Targets xar_read_header and XAR parsing code paths
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024; // 512KB
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enable XAR format specifically
|
||||
archive_read_support_format_xar(a);
|
||||
// Enable common filters
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
// Exercise entry metadata access
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_filetype(entry);
|
||||
archive_entry_uid(entry);
|
||||
archive_entry_gid(entry);
|
||||
|
||||
// Read data
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
44
contrib/oss-fuzz/libarchive_xar_fuzzer.dict
Normal file
44
contrib/oss-fuzz/libarchive_xar_fuzzer.dict
Normal file
@ -0,0 +1,44 @@
|
||||
# XAR format dictionary
|
||||
# Magic bytes
|
||||
"xar!"
|
||||
"\x78\x61\x72\x21"
|
||||
|
||||
# XML elements commonly in XAR
|
||||
"<xar>"
|
||||
"</xar>"
|
||||
"<toc>"
|
||||
"</toc>"
|
||||
"<file>"
|
||||
"</file>"
|
||||
"<name>"
|
||||
"</name>"
|
||||
"<data>"
|
||||
"</data>"
|
||||
"<encoding>"
|
||||
"</encoding>"
|
||||
"<archived-checksum>"
|
||||
"<extracted-checksum>"
|
||||
"<offset>"
|
||||
"<length>"
|
||||
"<size>"
|
||||
"<mode>"
|
||||
"<uid>"
|
||||
"<gid>"
|
||||
"<user>"
|
||||
"<group>"
|
||||
"<type>"
|
||||
"<mtime>"
|
||||
"<atime>"
|
||||
"<ctime>"
|
||||
|
||||
# Compression types
|
||||
"application/octet-stream"
|
||||
"application/x-gzip"
|
||||
"application/x-bzip2"
|
||||
"application/x-lzma"
|
||||
|
||||
# Checksum types
|
||||
"sha1"
|
||||
"md5"
|
||||
"sha256"
|
||||
"sha512"
|
||||
10
contrib/oss-fuzz/libarchive_xar_fuzzer.options
Normal file
10
contrib/oss-fuzz/libarchive_xar_fuzzer.options
Normal file
@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
68
contrib/oss-fuzz/libarchive_zip_fuzzer.cc
Normal file
68
contrib/oss-fuzz/libarchive_zip_fuzzer.cc
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* ZIP format fuzzer for libarchive
|
||||
* Tests ZIP with various compression methods and encryption
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "fuzz_helpers.h"
|
||||
|
||||
static constexpr size_t kMaxInputSize = 512 * 1024;
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) {
|
||||
if (len == 0 || len > kMaxInputSize) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct archive *a = archive_read_new();
|
||||
if (a == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
archive_read_support_format_zip(a);
|
||||
archive_read_support_filter_all(a);
|
||||
|
||||
// Add passphrase for encrypted ZIPs
|
||||
archive_read_add_passphrase(a, "password");
|
||||
archive_read_add_passphrase(a, "test");
|
||||
archive_read_add_passphrase(a, "");
|
||||
|
||||
// Enable ZIP options
|
||||
archive_read_set_options(a, "zip:ignorecrc32");
|
||||
|
||||
Buffer buffer = {buf, len, 0};
|
||||
if (archive_read_open(a, &buffer, NULL, reader_callback, NULL) != ARCHIVE_OK) {
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data_buffer(4096, 0);
|
||||
struct archive_entry *entry;
|
||||
|
||||
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
|
||||
archive_entry_pathname(entry);
|
||||
archive_entry_pathname_w(entry);
|
||||
archive_entry_size(entry);
|
||||
archive_entry_mtime(entry);
|
||||
archive_entry_mode(entry);
|
||||
archive_entry_is_encrypted(entry);
|
||||
archive_entry_is_data_encrypted(entry);
|
||||
archive_entry_is_metadata_encrypted(entry);
|
||||
|
||||
// Check compression name
|
||||
archive_format_name(a);
|
||||
archive_filter_name(a, 0);
|
||||
|
||||
ssize_t r;
|
||||
while ((r = archive_read_data(a, data_buffer.data(), data_buffer.size())) > 0)
|
||||
;
|
||||
}
|
||||
|
||||
archive_read_free(a);
|
||||
return 0;
|
||||
}
|
||||
43
contrib/oss-fuzz/libarchive_zip_fuzzer.dict
Normal file
43
contrib/oss-fuzz/libarchive_zip_fuzzer.dict
Normal file
@ -0,0 +1,43 @@
|
||||
# ZIP format dictionary
|
||||
|
||||
# Signatures
|
||||
"PK\x03\x04"
|
||||
"PK\x01\x02"
|
||||
"PK\x05\x06"
|
||||
"PK\x06\x06"
|
||||
"PK\x06\x07"
|
||||
"PK\x07\x08"
|
||||
|
||||
# Version needed
|
||||
"\x14\x00"
|
||||
"\x0a\x00"
|
||||
"\x2d\x00"
|
||||
"\x3f\x00"
|
||||
|
||||
# Compression methods
|
||||
"\x00\x00"
|
||||
"\x08\x00"
|
||||
"\x09\x00"
|
||||
"\x0c\x00"
|
||||
"\x0e\x00"
|
||||
"\x5f\x00"
|
||||
|
||||
# General purpose flags
|
||||
"\x00\x00"
|
||||
"\x01\x00"
|
||||
"\x08\x00"
|
||||
"\x09\x00"
|
||||
|
||||
# Extra field IDs
|
||||
"\x01\x00"
|
||||
"\x07\x00"
|
||||
"\x09\x00"
|
||||
"\x0a\x00"
|
||||
"\x15\x00"
|
||||
"\x17\x00"
|
||||
"\x55\x54"
|
||||
"\x75\x78"
|
||||
|
||||
# Encryption
|
||||
"\x01\x99"
|
||||
"\x02\x99"
|
||||
@ -1,16 +1,131 @@
|
||||
# build the project
|
||||
#!/bin/bash -eu
|
||||
|
||||
# Build the project
|
||||
./build/autogen.sh
|
||||
./configure
|
||||
make -j$(nproc) all
|
||||
|
||||
# build seed
|
||||
cp $SRC/libarchive/contrib/oss-fuzz/corpus.zip\
|
||||
$OUT/libarchive_fuzzer_seed_corpus.zip
|
||||
FUZZ_DIR=$SRC/libarchive/contrib/oss-fuzz
|
||||
TEST_DIR=$SRC/libarchive/libarchive/test
|
||||
|
||||
# build fuzzer(s)
|
||||
$CXX $CXXFLAGS -Ilibarchive \
|
||||
$SRC/libarchive/contrib/oss-fuzz/libarchive_fuzzer.cc \
|
||||
-o $OUT/libarchive_fuzzer $LIB_FUZZING_ENGINE \
|
||||
.libs/libarchive.a -Wl,-Bstatic -lbz2 -llzo2 \
|
||||
-lxml2 -llzma -lz -lcrypto -llz4 -licuuc \
|
||||
-licudata -Wl,-Bdynamic
|
||||
# Common libraries for linking
|
||||
LIBS=".libs/libarchive.a -Wl,-Bstatic -lbz2 -llzo2 -lxml2 -llzma -lz -lcrypto -llz4 -licuuc -licudata -Wl,-Bdynamic"
|
||||
|
||||
# Function to build a fuzzer
|
||||
build_fuzzer() {
|
||||
local name=$1
|
||||
local source=$2
|
||||
echo "Building fuzzer: $name"
|
||||
$CXX $CXXFLAGS -Ilibarchive \
|
||||
"$source" \
|
||||
-o "$OUT/$name" $LIB_FUZZING_ENGINE $LIBS
|
||||
}
|
||||
|
||||
# Build all format-specific fuzzers
|
||||
FUZZERS=(
|
||||
"libarchive_fuzzer"
|
||||
"libarchive_tar_fuzzer"
|
||||
"libarchive_zip_fuzzer"
|
||||
"libarchive_7zip_fuzzer"
|
||||
"libarchive_rar_fuzzer"
|
||||
"libarchive_rar5_fuzzer"
|
||||
"libarchive_xar_fuzzer"
|
||||
"libarchive_cab_fuzzer"
|
||||
"libarchive_lha_fuzzer"
|
||||
"libarchive_iso9660_fuzzer"
|
||||
"libarchive_cpio_fuzzer"
|
||||
"libarchive_warc_fuzzer"
|
||||
"libarchive_mtree_fuzzer"
|
||||
"libarchive_ar_fuzzer"
|
||||
"libarchive_filter_fuzzer"
|
||||
"libarchive_entry_fuzzer"
|
||||
"libarchive_write_fuzzer"
|
||||
"libarchive_linkify_fuzzer"
|
||||
"libarchive_match_fuzzer"
|
||||
"libarchive_encryption_fuzzer"
|
||||
"libarchive_read_disk_fuzzer"
|
||||
"libarchive_write_disk_fuzzer"
|
||||
"libarchive_seek_fuzzer"
|
||||
"libarchive_string_fuzzer"
|
||||
"libarchive_roundtrip_fuzzer"
|
||||
)
|
||||
|
||||
for fuzzer in "${FUZZERS[@]}"; do
|
||||
if [ -f "$FUZZ_DIR/${fuzzer}.cc" ]; then
|
||||
build_fuzzer "$fuzzer" "$FUZZ_DIR/${fuzzer}.cc"
|
||||
fi
|
||||
done
|
||||
|
||||
# Copy dictionaries and options
|
||||
cp "$FUZZ_DIR"/*.dict "$OUT/" 2>/dev/null || true
|
||||
cp "$FUZZ_DIR"/*.options "$OUT/" 2>/dev/null || true
|
||||
|
||||
# Build seed corpora
|
||||
echo "Building seed corpora..."
|
||||
|
||||
# Main fuzzer corpus (existing)
|
||||
cp "$FUZZ_DIR/corpus.zip" "$OUT/libarchive_fuzzer_seed_corpus.zip"
|
||||
|
||||
# Function to create corpus from test files
|
||||
create_corpus() {
|
||||
local name=$1
|
||||
local pattern=$2
|
||||
local dir="/tmp/${name}_corpus"
|
||||
|
||||
mkdir -p "$dir"
|
||||
for f in $TEST_DIR/$pattern; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "$dir/$base" "$f" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$(ls -A $dir 2>/dev/null)" ]; then
|
||||
zip -j "$OUT/${name}_seed_corpus.zip" "$dir"/* 2>/dev/null || true
|
||||
echo "Created corpus for $name with $(ls $dir | wc -l) files"
|
||||
fi
|
||||
rm -rf "$dir"
|
||||
}
|
||||
|
||||
# Create format-specific corpora
|
||||
create_corpus "libarchive_tar_fuzzer" "test_compat_*tar*.uu"
|
||||
create_corpus "libarchive_zip_fuzzer" "test_*zip*.uu"
|
||||
create_corpus "libarchive_7zip_fuzzer" "test_read_format_7zip*.uu"
|
||||
create_corpus "libarchive_rar_fuzzer" "test_read_format_rar_*.uu"
|
||||
create_corpus "libarchive_rar5_fuzzer" "test_read_format_rar5*.uu"
|
||||
create_corpus "libarchive_xar_fuzzer" "test_read_format_xar*.uu"
|
||||
create_corpus "libarchive_cab_fuzzer" "test_read_format_cab*.uu"
|
||||
create_corpus "libarchive_lha_fuzzer" "test_read_format_lha*.uu"
|
||||
create_corpus "libarchive_iso9660_fuzzer" "test_read_format_iso*.uu"
|
||||
create_corpus "libarchive_cpio_fuzzer" "test_compat_cpio*.uu"
|
||||
create_corpus "libarchive_warc_fuzzer" "test_read_format_warc*.uu"
|
||||
create_corpus "libarchive_mtree_fuzzer" "test_read_format_mtree*.uu"
|
||||
create_corpus "libarchive_ar_fuzzer" "test_read_format_ar*.uu"
|
||||
|
||||
# Filter corpus - use compressed test files
|
||||
mkdir -p /tmp/filter_corpus
|
||||
for f in $TEST_DIR/*.gz.uu $TEST_DIR/*.bz2.uu $TEST_DIR/*.xz.uu $TEST_DIR/*.lz4.uu $TEST_DIR/*.zst.uu $TEST_DIR/*.Z.uu; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "/tmp/filter_corpus/$base" "$f" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
if [ "$(ls -A /tmp/filter_corpus 2>/dev/null)" ]; then
|
||||
zip -j "$OUT/libarchive_filter_fuzzer_seed_corpus.zip" /tmp/filter_corpus/* 2>/dev/null || true
|
||||
fi
|
||||
rm -rf /tmp/filter_corpus
|
||||
|
||||
# Encryption corpus - encrypted archives
|
||||
mkdir -p /tmp/encryption_corpus
|
||||
for f in $TEST_DIR/*encrypt*.uu $TEST_DIR/*password*.uu; do
|
||||
if [ -f "$f" ]; then
|
||||
base=$(basename "$f" .uu)
|
||||
uudecode -o "/tmp/encryption_corpus/$base" "$f" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
if [ "$(ls -A /tmp/encryption_corpus 2>/dev/null)" ]; then
|
||||
zip -j "$OUT/libarchive_encryption_fuzzer_seed_corpus.zip" /tmp/encryption_corpus/* 2>/dev/null || true
|
||||
fi
|
||||
rm -rf /tmp/encryption_corpus
|
||||
|
||||
echo "Build complete! Built ${#FUZZERS[@]} fuzzers."
|
||||
|
||||
@ -725,7 +725,7 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
|
||||
if (cpio->uid_override >= 0)
|
||||
archive_entry_set_uid(entry, cpio->uid_override);
|
||||
if (cpio->gname_override != NULL)
|
||||
if (cpio->uname_override != NULL)
|
||||
archive_entry_set_uname(entry, cpio->uname_override);
|
||||
if (cpio->gid_override >= 0)
|
||||
archive_entry_set_gid(entry, cpio->gid_override);
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008004
|
||||
#define ARCHIVE_VERSION_NUMBER 3009000
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
@ -177,7 +177,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.4"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.9.0dev"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
@ -210,7 +210,9 @@ __LA_DECL const char * archive_openssl_version(void);
|
||||
__LA_DECL const char * archive_libmd_version(void);
|
||||
__LA_DECL const char * archive_commoncrypto_version(void);
|
||||
__LA_DECL const char * archive_cng_version(void);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
__LA_DECL const char * archive_wincrypt_version(void);
|
||||
#endif
|
||||
__LA_DECL const char * archive_librichacl_version(void);
|
||||
__LA_DECL const char * archive_libacl_version(void);
|
||||
__LA_DECL const char * archive_libattr_version(void);
|
||||
|
||||
@ -57,7 +57,7 @@ pbkdf2_sha1(const char *pw, size_t pw_len, const uint8_t *salt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment(lib, "Bcrypt.lib")
|
||||
#endif
|
||||
@ -197,7 +197,7 @@ aes_ctr_release(archive_crypto_ctx *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
|
||||
static int
|
||||
aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
|
||||
|
||||
@ -62,7 +62,7 @@ typedef struct {
|
||||
size_t encr_pos;
|
||||
} archive_crypto_ctx;
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_CNG 1
|
||||
|
||||
@ -144,16 +144,6 @@ typedef struct {
|
||||
|
||||
#else
|
||||
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
typedef int archive_crypto_ctx;
|
||||
|
||||
@ -44,16 +44,11 @@
|
||||
/*
|
||||
* Message digest functions for Windows platform.
|
||||
*/
|
||||
#if defined(ARCHIVE_CRYPTO_MD5_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA1_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#if defined(HAVE_BCRYPT_H)
|
||||
|
||||
/*
|
||||
* Initialize a Message digest.
|
||||
*/
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
static int
|
||||
win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
|
||||
{
|
||||
@ -72,30 +67,6 @@ win_crypto_init(Digest_CTX *ctx, const WCHAR *algo)
|
||||
ctx->valid = 1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
#else
|
||||
static int
|
||||
win_crypto_init(Digest_CTX *ctx, DWORD prov, ALG_ID algId)
|
||||
{
|
||||
|
||||
ctx->valid = 0;
|
||||
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
|
||||
prov, CRYPT_VERIFYCONTEXT)) {
|
||||
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
|
||||
return (ARCHIVE_FAILED);
|
||||
if (!CryptAcquireContext(&ctx->cryptProv, NULL, NULL,
|
||||
prov, CRYPT_NEWKEYSET))
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
if (!CryptCreateHash(ctx->cryptProv, algId, 0, 0, &ctx->hash)) {
|
||||
CryptReleaseContext(ctx->cryptProv, 0);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
||||
ctx->valid = 1;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update a Message digest.
|
||||
@ -107,42 +78,26 @@ win_crypto_Update(Digest_CTX *ctx, const unsigned char *buf, size_t len)
|
||||
if (!ctx->valid)
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
BCryptHashData(ctx->hHash,
|
||||
(PUCHAR)(uintptr_t)buf,
|
||||
(ULONG)len, 0);
|
||||
#else
|
||||
CryptHashData(ctx->hash,
|
||||
(unsigned char *)(uintptr_t)buf,
|
||||
(DWORD)len, 0);
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
win_crypto_Final(unsigned char *buf, size_t bufsize, Digest_CTX *ctx)
|
||||
{
|
||||
#if !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
DWORD siglen = (DWORD)bufsize;
|
||||
#endif
|
||||
|
||||
if (!ctx->valid)
|
||||
return (ARCHIVE_FAILED);
|
||||
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
BCryptFinishHash(ctx->hHash, buf, (ULONG)bufsize, 0);
|
||||
BCryptDestroyHash(ctx->hHash);
|
||||
BCryptCloseAlgorithmProvider(ctx->hAlg, 0);
|
||||
#else
|
||||
CryptGetHashParam(ctx->hash, HP_HASHVAL, buf, &siglen, 0);
|
||||
CryptDestroyHash(ctx->hash);
|
||||
CryptReleaseContext(ctx->cryptProv, 0);
|
||||
#endif
|
||||
ctx->valid = 0;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif /* defined(ARCHIVE_CRYPTO_*_WIN) */
|
||||
#endif /* defined(HAVE_BCRYPT_H) */
|
||||
|
||||
|
||||
/* MD5 implementations */
|
||||
@ -234,11 +189,7 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -645,11 +596,7 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -925,11 +872,7 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1177,11 +1120,7 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1453,11 +1392,7 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@ -165,8 +165,7 @@
|
||||
defined(ARCHIVE_CRYPTO_SHA256_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA384_WIN) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/* don't use bcrypt when XP needs to be supported */
|
||||
#if defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTO_CNG 1
|
||||
typedef struct {
|
||||
@ -174,15 +173,6 @@ typedef struct {
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
BCRYPT_HASH_HANDLE hHash;
|
||||
} Digest_CTX;
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#define ARCHIVE_CRYPTO_WINCRYPT 1
|
||||
typedef struct {
|
||||
int valid;
|
||||
HCRYPTPROV cryptProv;
|
||||
HCRYPTHASH hash;
|
||||
} Digest_CTX;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3008004
|
||||
#define ARCHIVE_VERSION_NUMBER 3009000
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
|
||||
@ -74,7 +74,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
}
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
|
||||
#ifndef BCRYPT_HASH_REUSABLE_FLAG
|
||||
# define BCRYPT_HASH_REUSABLE_FLAG 0x00000020
|
||||
|
||||
@ -52,7 +52,7 @@ int __libarchive_hmac_build_hack(void);
|
||||
|
||||
typedef CCHmacContext archive_hmac_sha1_ctx;
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
|
||||
typedef struct {
|
||||
|
||||
@ -57,19 +57,13 @@ static void la_arc4random_buf(void *, size_t);
|
||||
#include "archive.h"
|
||||
#include "archive_random_private.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/* don't use bcrypt when XP needs to be supported */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
|
||||
/* Common in other bcrypt implementations, but missing from VS2008. */
|
||||
#ifndef BCRYPT_SUCCESS
|
||||
#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
|
||||
#endif
|
||||
|
||||
#elif defined(HAVE_WINCRYPT_H)
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
@ -85,7 +79,6 @@ int
|
||||
archive_random(void *buf, size_t nbytes)
|
||||
{
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
# if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
NTSTATUS status;
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
|
||||
@ -98,25 +91,6 @@ archive_random(void *buf, size_t nbytes)
|
||||
return ARCHIVE_FAILED;
|
||||
|
||||
return ARCHIVE_OK;
|
||||
# else
|
||||
HCRYPTPROV hProv;
|
||||
BOOL success;
|
||||
|
||||
success = CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT);
|
||||
if (!success && GetLastError() == (DWORD)NTE_BAD_KEYSET) {
|
||||
success = CryptAcquireContext(&hProv, NULL, NULL,
|
||||
PROV_RSA_FULL, CRYPT_NEWKEYSET);
|
||||
}
|
||||
if (success) {
|
||||
success = CryptGenRandom(hProv, (DWORD)nbytes, (BYTE*)buf);
|
||||
CryptReleaseContext(hProv, 0);
|
||||
if (success)
|
||||
return ARCHIVE_OK;
|
||||
}
|
||||
/* TODO: Does this case really happen? */
|
||||
return ARCHIVE_FAILED;
|
||||
# endif
|
||||
#elif !defined(HAVE_ARC4RANDOM_BUF) && (!defined(_WIN32) || defined(__CYGWIN__))
|
||||
la_arc4random_buf(buf, nbytes);
|
||||
return ARCHIVE_OK;
|
||||
|
||||
@ -1468,7 +1468,7 @@ update_current_filesystem(struct archive_read_disk *a, int64_t dev)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
t->filesystem_table = (struct filesystem *)p;
|
||||
t->allocated_filesystem = (int)s;
|
||||
t->allocated_filesystem = s;
|
||||
}
|
||||
t->current_filesystem_id = fid;
|
||||
t->current_filesystem = &(t->filesystem_table[fid]);
|
||||
|
||||
@ -232,8 +232,8 @@ bid_get_line(struct archive_read_filter *filter,
|
||||
size_t nbytes_req = (*ravail+1023) & ~1023U;
|
||||
ssize_t tested;
|
||||
|
||||
/* Increase reading bytes if it is not enough to at least
|
||||
* new two lines. */
|
||||
/* Increase reading bytes if it is not enough for at least
|
||||
* two new lines. */
|
||||
if (nbytes_req < (size_t)*ravail + 160)
|
||||
nbytes_req <<= 1;
|
||||
|
||||
@ -411,7 +411,7 @@ ensure_in_buff_size(struct archive_read_filter *self,
|
||||
|
||||
/*
|
||||
* Calculate a new buffer size for in_buff.
|
||||
* Increase its value until it has enough size we need.
|
||||
* Increase its value until it is enough for our needs.
|
||||
*/
|
||||
newsize = uudecode->in_allocated;
|
||||
do {
|
||||
@ -494,7 +494,7 @@ read_more:
|
||||
}
|
||||
/*
|
||||
* If there is remaining data which is saved by
|
||||
* previous calling, use it first.
|
||||
* a previous call, use it first.
|
||||
*/
|
||||
if (ensure_in_buff_size(self, uudecode,
|
||||
avail_in + uudecode->in_cnt) != ARCHIVE_OK)
|
||||
|
||||
@ -2813,7 +2813,7 @@ lzx_decode_blocks(struct lzx_stream *strm, int last)
|
||||
lzx_br_bits(&bre, mt_max_bits));
|
||||
lzx_br_consume(&bre, mt_bitlen[c]);
|
||||
}
|
||||
if (c > UCHAR_MAX)
|
||||
if ((unsigned int)c > UCHAR_MAX)
|
||||
break;
|
||||
/*
|
||||
* 'c' is exactly literal code.
|
||||
|
||||
@ -825,9 +825,9 @@ header_odc(struct archive_read *a, struct cpio *cpio,
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: if a filename suffix is ".z", it is the file gziped by afio.
|
||||
* it would be nice that we can show uncompressed file size and we can
|
||||
* uncompressed file contents automatically, unfortunately we have nothing
|
||||
* NOTE: if a filename suffix is ".z", it is a file gzipped by afio.
|
||||
* it would be nice if we could show uncompressed file size and
|
||||
* uncompress file contents automatically, unfortunately we have nothing
|
||||
* to get a uncompressed file size while reading each header. It means
|
||||
* we also cannot uncompress file contents under our framework.
|
||||
*/
|
||||
|
||||
@ -2374,7 +2374,7 @@ lzh_decode_blocks(struct lzh_stream *strm, int last)
|
||||
lzh_br_consume(&bre, lt_bitlen[c]);
|
||||
}
|
||||
blocks_avail--;
|
||||
if (c > UCHAR_MAX)
|
||||
if ((unsigned int)c > UCHAR_MAX)
|
||||
/* Current block is a match data. */
|
||||
break;
|
||||
/*
|
||||
|
||||
@ -392,8 +392,8 @@ next_line(struct archive_read *a,
|
||||
if (len >= MAX_LINE_LEN)
|
||||
return (-1);
|
||||
|
||||
/* Increase reading bytes if it is not enough to at least
|
||||
* new two lines. */
|
||||
/* Increase reading bytes if it is not enough for at least
|
||||
* two new lines. */
|
||||
if (nbytes_req < (size_t)*ravail + 160)
|
||||
nbytes_req <<= 1;
|
||||
|
||||
@ -568,8 +568,8 @@ bid_keyword_list(const char *p, ssize_t len, int unset, int last_is_path)
|
||||
--len;
|
||||
value = 1;
|
||||
}
|
||||
/* A keyword should have a its value unless
|
||||
* "/unset" operation. */
|
||||
/* A keyword should have a value unless this is
|
||||
* an "/unset" operation. */
|
||||
if (!unset && value == 0)
|
||||
return (-1);
|
||||
}
|
||||
@ -752,7 +752,7 @@ detect_form(struct archive_read *a, int *is_form_d)
|
||||
} else if (form_D == 1) {
|
||||
if (!last_is_path && keywords > 0)
|
||||
/* This this is not `form D'
|
||||
* and We cannot accept mixed
|
||||
* and we cannot accept mixed
|
||||
* format. */
|
||||
break;
|
||||
}
|
||||
@ -805,7 +805,7 @@ detect_form(struct archive_read *a, int *is_form_d)
|
||||
* to read the entire mtree file into memory up front.
|
||||
*
|
||||
* The parsing is done in two steps. First, it is decided if a line
|
||||
* changes the global defaults and if it is, processed accordingly.
|
||||
* changes the global defaults and if it does, it is processed accordingly.
|
||||
* Otherwise, the options of the line are merged with the current
|
||||
* global options.
|
||||
*/
|
||||
|
||||
@ -3573,7 +3573,7 @@ win_strncat_from_utf16(struct archive_string *as, const void *_p, size_t bytes,
|
||||
|
||||
if (sc->to_cp == CP_C_LOCALE) {
|
||||
/*
|
||||
* "C" locale special process.
|
||||
* "C" locale special processing.
|
||||
*/
|
||||
u16 = _p;
|
||||
ll = 0;
|
||||
@ -3690,7 +3690,7 @@ win_strncat_to_utf16(struct archive_string *as16, const void *_p,
|
||||
avail = as16->buffer_length - 2;
|
||||
if (sc->from_cp == CP_C_LOCALE) {
|
||||
/*
|
||||
* "C" locale special process.
|
||||
* "C" locale special processing.
|
||||
*/
|
||||
count = 0;
|
||||
while (count < length && *s) {
|
||||
|
||||
@ -42,17 +42,13 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/* don't use bcrypt when XP needs to be supported */
|
||||
#if defined(HAVE_BCRYPT_H)
|
||||
#include <bcrypt.h>
|
||||
|
||||
/* Common in other bcrypt implementations, but missing from VS2008. */
|
||||
#ifndef BCRYPT_SUCCESS
|
||||
#define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS)
|
||||
#endif
|
||||
|
||||
#elif defined(HAVE_WINCRYPT_H)
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB_H
|
||||
@ -250,11 +246,7 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
|
||||
DWORD attr;
|
||||
wchar_t *xp, *ep;
|
||||
int fd;
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
BCRYPT_ALG_HANDLE hAlg = NULL;
|
||||
#else
|
||||
HCRYPTPROV hProv = (HCRYPTPROV)NULL;
|
||||
#endif
|
||||
fd = -1;
|
||||
ws = NULL;
|
||||
archive_string_init(&temp_name);
|
||||
@ -328,19 +320,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
|
||||
abort();
|
||||
}
|
||||
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM,
|
||||
NULL, 0))) {
|
||||
la_dosmaperr(GetLastError());
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
#else
|
||||
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT)) {
|
||||
la_dosmaperr(GetLastError());
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
wchar_t *p;
|
||||
@ -351,19 +335,11 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
|
||||
|
||||
/* Generate a random file name through CryptGenRandom(). */
|
||||
p = xp;
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p,
|
||||
(DWORD)(ep - p)*sizeof(wchar_t), 0))) {
|
||||
la_dosmaperr(GetLastError());
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
#else
|
||||
if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
|
||||
(BYTE*)p)) {
|
||||
la_dosmaperr(GetLastError());
|
||||
goto exit_tmpfile;
|
||||
}
|
||||
#endif
|
||||
for (; p < ep; p++)
|
||||
*p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
|
||||
|
||||
@ -417,13 +393,8 @@ __archive_mktempx(const char *tmpdir, wchar_t *template)
|
||||
break;/* success! */
|
||||
}
|
||||
exit_tmpfile:
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
if (hAlg != NULL)
|
||||
BCryptCloseAlgorithmProvider(hAlg, 0);
|
||||
#else
|
||||
if (hProv != (HCRYPTPROV)NULL)
|
||||
CryptReleaseContext(hProv, 0);
|
||||
#endif
|
||||
free(ws);
|
||||
if (template == temp_name.s)
|
||||
archive_wstring_free(&temp_name);
|
||||
@ -456,7 +427,7 @@ __archive_issetugid(void)
|
||||
return (-1);
|
||||
if (ruid != euid || ruid != suid)
|
||||
return (1);
|
||||
if (getresgid(&ruid, &egid, &sgid) != 0)
|
||||
if (getresgid(&rgid, &egid, &sgid) != 0)
|
||||
return (-1);
|
||||
if (rgid != egid || rgid != sgid)
|
||||
return (1);
|
||||
|
||||
@ -157,10 +157,6 @@ archive_crypto_version(struct archive_string* str)
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_LIBMD)
|
||||
archive_strcat(str, " libmd/");
|
||||
archive_strcat(str, archive_libmd_version());
|
||||
#endif
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT)
|
||||
archive_strcat(str, " WinCrypt/");
|
||||
archive_strcat(str, archive_wincrypt_version());
|
||||
#endif
|
||||
// Just in case
|
||||
(void)str; /* UNUSED */
|
||||
@ -431,27 +427,7 @@ archive_cng_version(void)
|
||||
const char *
|
||||
archive_wincrypt_version(void)
|
||||
{
|
||||
#if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT)
|
||||
HCRYPTPROV prov;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
|
||||
if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
|
||||
return NULL;
|
||||
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
|
||||
return NULL;
|
||||
}
|
||||
DWORD version, length = sizeof(version);
|
||||
if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) {
|
||||
return NULL;
|
||||
} else {
|
||||
char major = (version >> 8) & 0xFF;
|
||||
char minor = version & 0xFF;
|
||||
static char wincrypt_version[6];
|
||||
snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor);
|
||||
return wincrypt_version;
|
||||
}
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
|
||||
@ -253,7 +253,7 @@ la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
createExParams.dwSize = sizeof(createExParams);
|
||||
createExParams.dwFileAttributes = dwFlagsAndAttributes & 0xFFFF;
|
||||
createExParams.dwFileFlags = dwFlagsAndAttributes & 0xFFF00000;
|
||||
createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F00000;
|
||||
createExParams.dwSecurityQosFlags = dwFlagsAndAttributes & 0x000F0000;
|
||||
createExParams.lpSecurityAttributes = lpSecurityAttributes;
|
||||
createExParams.hTemplateFile = hTemplateFile;
|
||||
handle = CreateFile2(wpath, dwDesiredAccess, dwShareMode,
|
||||
@ -747,7 +747,8 @@ __la_seek_fstat(int fd, la_seek_stat_t *st)
|
||||
int ret;
|
||||
|
||||
ret = __hstat((HANDLE)_get_osfhandle(fd), &u);
|
||||
copy_seek_stat(st, &u);
|
||||
if (ret >= 0)
|
||||
copy_seek_stat(st, &u);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
@ -135,11 +135,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
|
||||
static int
|
||||
file_free(struct archive *a, void *client_data)
|
||||
{
|
||||
struct write_fd_data *mine = (struct write_fd_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
if (mine == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
free(mine);
|
||||
free(client_data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -96,11 +96,7 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
|
||||
static int
|
||||
file_free(struct archive *a, void *client_data)
|
||||
{
|
||||
struct write_FILE_data *mine = client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
if (mine == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
free(mine);
|
||||
free(client_data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -104,11 +104,7 @@ memory_write(struct archive *a, void *client_data, const void *buff, size_t leng
|
||||
static int
|
||||
memory_write_free(struct archive *a, void *client_data)
|
||||
{
|
||||
struct write_memory_data *mine;
|
||||
(void)a; /* UNUSED */
|
||||
mine = client_data;
|
||||
if (mine == NULL)
|
||||
return (ARCHIVE_OK);
|
||||
free(mine);
|
||||
free(client_data);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
@ -144,7 +144,9 @@ archive_write_set_format_shar_dump(struct archive *_a)
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
struct shar *shar;
|
||||
|
||||
archive_write_set_format_shar(&a->archive);
|
||||
int ret = archive_write_set_format_shar(&a->archive);
|
||||
if (ret != ARCHIVE_OK)
|
||||
return ret;
|
||||
shar = (struct shar *)a->format_data;
|
||||
shar->dump = 1;
|
||||
a->format_write_data = archive_write_shar_data_uuencode;
|
||||
@ -240,6 +242,7 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
shar_quote(&shar->work, p, 1);
|
||||
archive_strcat(&shar->work,
|
||||
" > /dev/null 2>&1\n");
|
||||
free(shar->last_dir);
|
||||
shar->last_dir = p;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -539,7 +539,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
|
||||
ret = ARCHIVE_WARN;
|
||||
}
|
||||
if (copy_length > 0) {
|
||||
if (strlen(p) > USTAR_gname_size) {
|
||||
if (copy_length > USTAR_gname_size) {
|
||||
if (tartype != 'x') {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Group name too long");
|
||||
|
||||
@ -47,7 +47,7 @@ echo "f3" > $dir/d1/f3
|
||||
rm -r $dir
|
||||
}
|
||||
#
|
||||
# Make a lzip file from split tar file.
|
||||
# Make a lzip file from the split tar file.
|
||||
#
|
||||
name=test_compat_lzip_1
|
||||
dir="$name`date +%Y%m%d%H%M%S`.$USER"
|
||||
@ -75,7 +75,7 @@ exit 0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Verify our ability to read sample files compatibly with lzip.
|
||||
* Verify our ability to read the sample files compatibly with lzip.
|
||||
*
|
||||
* In particular:
|
||||
* * lzip will read multiple lzip streams, concatenating the output
|
||||
|
||||
@ -64,6 +64,8 @@ lafe_line_reader(const char *pathname, int nullSeparator)
|
||||
|
||||
lr->nullSeparator = nullSeparator;
|
||||
lr->pathname = strdup(pathname);
|
||||
if (lr->pathname == NULL)
|
||||
lafe_errc(1, ENOMEM, "Can't open %s", pathname);
|
||||
|
||||
if (strcmp(pathname, "-") == 0)
|
||||
lr->f = stdin;
|
||||
|
||||
16
tar/subst.c
16
tar/subst.c
@ -237,7 +237,7 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
|
||||
|
||||
char isEnd = 0;
|
||||
do {
|
||||
isEnd = *name == '\0';
|
||||
isEnd = *name == '\0';
|
||||
if (regexec(&rule->re, name, 10, matches, 0))
|
||||
break;
|
||||
|
||||
@ -293,13 +293,13 @@ apply_substitution(struct bsdtar *bsdtar, const char *name, char **result,
|
||||
|
||||
realloc_strcat(result, rule->result + j);
|
||||
if (matches[0].rm_eo > 0) {
|
||||
name += matches[0].rm_eo;
|
||||
} else {
|
||||
// We skip a character because the match is 0-length
|
||||
// so we need to add it to the output
|
||||
realloc_strncat(result, name, 1);
|
||||
name += 1;
|
||||
}
|
||||
name += matches[0].rm_eo;
|
||||
} else if (!isEnd) {
|
||||
// We skip a character because the match is 0-length
|
||||
// so we need to add it to the output
|
||||
realloc_strncat(result, name, 1);
|
||||
name += 1;
|
||||
}
|
||||
} while (rule->global && !isEnd); // Testing one step after because sed et al. run 0-length patterns a last time on the empty string at the end
|
||||
}
|
||||
|
||||
|
||||
@ -163,7 +163,7 @@ set_writer_options(struct bsdtar *bsdtar, struct archive *a)
|
||||
* a format or filters which are not added to
|
||||
* the archive write object. */
|
||||
memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
|
||||
memcpy(p, writer_options, opt_len);
|
||||
memcpy(p + module_len, writer_options, opt_len);
|
||||
r = archive_write_set_options(a, p);
|
||||
free(p);
|
||||
if (r < ARCHIVE_WARN)
|
||||
@ -190,13 +190,12 @@ set_reader_options(struct bsdtar *bsdtar, struct archive *a)
|
||||
char *p;
|
||||
/* Set default write options. */
|
||||
if ((p = malloc(module_len + opt_len)) == NULL)
|
||||
if (p == NULL)
|
||||
lafe_errc(1, errno, "Out of memory");
|
||||
/* Prepend magic code to ignore options for
|
||||
* a format or filters which are not added to
|
||||
* the archive write object. */
|
||||
memcpy(p, IGNORE_WRONG_MODULE_NAME, module_len);
|
||||
memcpy(p, reader_options, opt_len);
|
||||
memcpy(p + module_len, reader_options, opt_len);
|
||||
r = archive_read_set_options(a, p);
|
||||
free(p);
|
||||
if (r < ARCHIVE_WARN)
|
||||
|
||||
@ -3681,11 +3681,19 @@ test_run(int i, const char *tmpdir)
|
||||
*/
|
||||
|
||||
static void
|
||||
usage(const char *program)
|
||||
list_tests(void)
|
||||
{
|
||||
static const int limit = nitems(tests);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < limit; i++)
|
||||
printf(" %d: %s\n", i, tests[i].name);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *program)
|
||||
{
|
||||
|
||||
printf("Usage: %s [options] <test> <test> ...\n", program);
|
||||
printf("Default is to run all tests.\n");
|
||||
printf("Otherwise, specify the numbers of the tests you wish to run.\n");
|
||||
@ -3693,6 +3701,8 @@ usage(const char *program)
|
||||
printf(" -d Dump core after any failure, for debugging.\n");
|
||||
printf(" -k Keep all temp files.\n");
|
||||
printf(" Default: temp files for successful tests deleted.\n");
|
||||
printf(" -l List available tests and exit, ignoring all other.\n");
|
||||
printf(" options and arguments.\n");
|
||||
#ifdef PROGRAM
|
||||
printf(" -p <path> Path to executable to be tested.\n");
|
||||
printf(" Default: path taken from " ENVBASE " environment variable.\n");
|
||||
@ -3704,8 +3714,7 @@ usage(const char *program)
|
||||
printf(" -u Keep running specified tests until one fails.\n");
|
||||
printf(" -v Verbose.\n");
|
||||
printf("Available tests:\n");
|
||||
for (i = 0; i < limit; i++)
|
||||
printf(" %d: %s\n", i, tests[i].name);
|
||||
list_tests();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -4079,6 +4088,10 @@ main(int argc, char **argv)
|
||||
case 'k':
|
||||
keep_temp_files = 1;
|
||||
break;
|
||||
case 'l':
|
||||
list_tests();
|
||||
exit(0);
|
||||
break;
|
||||
case 'p':
|
||||
#ifdef PROGRAM
|
||||
testprogfile = option_arg;
|
||||
|
||||
@ -654,11 +654,11 @@ recheck:
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_N
|
||||
sb.st_mtime > mtime.tv_sec ||
|
||||
(sb.st_mtime == mtime.tv_sec &&
|
||||
sb.st_mtime_n => mtime.tv_nsec)
|
||||
sb.st_mtime_n >= mtime.tv_nsec)
|
||||
#elif HAVE_STRUCT_STAT_ST_MTIME_USEC
|
||||
sb.st_mtime > mtime.tv_sec ||
|
||||
(sb.st_mtime == mtime.tv_sec &&
|
||||
sb.st_mtime_usec => mtime.tv_nsec / 1000)
|
||||
sb.st_mtime_usec >= mtime.tv_nsec / 1000)
|
||||
#else
|
||||
sb.st_mtime > mtime.tv_sec
|
||||
#endif
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
* _SWAP + + + +
|
||||
*/
|
||||
#ifdef QUEUE_MACRO_DEBUG
|
||||
#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
|
||||
#warning Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
|
||||
#define QUEUE_MACRO_DEBUG_TRACE
|
||||
#define QUEUE_MACRO_DEBUG_TRASH
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user