Compare commits
472
Commits
mingw-fixes
...
patch/3.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27cbc78271 | ||
|
|
9f08f77e61 | ||
|
|
c79cf80dbc | ||
|
|
db52c65ddc | ||
|
|
55894641b2 | ||
|
|
a3189af7c7 | ||
|
|
773061ff4c | ||
|
|
e8999de183 | ||
|
|
0eb1dabdae | ||
|
|
12d40a22e0 | ||
|
|
41180e15fc | ||
|
|
45f7ec5422 | ||
|
|
1e17c0bc07 | ||
|
|
11077ac395 | ||
|
|
c1953e8d12 | ||
|
|
783003f1f5 | ||
|
|
5be8bf4704 | ||
|
|
764c006ee6 | ||
|
|
5a2845f14c | ||
|
|
da6d06288f | ||
|
|
29f3af2f5b | ||
|
|
a50aed7cb1 | ||
|
|
9dde11c5a2 | ||
|
|
148a9f90c1 | ||
|
|
c0dcda10c0 | ||
|
|
7007cebd12 | ||
|
|
764da28499 | ||
|
|
825d6a6049 | ||
|
|
54f11c3480 | ||
|
|
15fe82079b | ||
|
|
d3729ca1b5 | ||
|
|
9825d81a78 | ||
|
|
918cb1779e | ||
|
|
696cb76f1b | ||
|
|
1615b934f8 | ||
|
|
2733e72b47 | ||
|
|
f171098f18 | ||
|
|
2e0028f32d | ||
|
|
2592af3ef2 | ||
|
|
793829d87d | ||
|
|
d7d4d41c4c | ||
|
|
048a2ad207 | ||
|
|
2631a5fb75 | ||
|
|
32e07d6c8e | ||
|
|
b09472e769 | ||
|
|
172240f7eb | ||
|
|
febce1c072 | ||
|
|
1a4c198239 | ||
|
|
be6f3d7aa6 | ||
|
|
665a8ccd25 | ||
|
|
9b850de4bc | ||
|
|
6b919b34bd | ||
|
|
3e09b6805c | ||
|
|
cf80ac317e | ||
|
|
96a2a6c008 | ||
|
|
cdce9e7943 | ||
|
|
e61c920fa7 | ||
|
|
0c7012eb12 | ||
|
|
63f4a201df | ||
|
|
9bff9c306f | ||
|
|
946fd38679 | ||
|
|
fce49a37b6 | ||
|
|
4aa4582929 | ||
|
|
ffc1114f84 | ||
|
|
2de73db12b | ||
|
|
86e60964f5 | ||
|
|
e8f39f1516 | ||
|
|
22ffe8e8e4 | ||
|
|
a5a6785ffb | ||
|
|
7920c04f99 | ||
|
|
5e09594094 | ||
|
|
3de8f12efd | ||
|
|
69e9ab7548 | ||
|
|
398569dfc7 | ||
|
|
4e7c55e73a | ||
|
|
e25f689b12 | ||
|
|
165edb3611 | ||
|
|
e067c7884f | ||
|
|
01d1c12ce8 | ||
|
|
5e87e36637 | ||
|
|
710f837b31 | ||
|
|
858509c392 | ||
|
|
e378a5bb09 | ||
|
|
79ec62a5c1 | ||
|
|
4bb52f4934 | ||
|
|
2c9e5b41b8 | ||
|
|
2049eed5fd | ||
|
|
c18d2aa7eb | ||
|
|
7231e54e22 | ||
|
|
1cafc7ab96 | ||
|
|
97b636b573 | ||
|
|
bca61a0d8d | ||
|
|
d598dc1ce5 | ||
|
|
8fff248d1d | ||
|
|
1c4887075f | ||
|
|
dedf6d53d9 | ||
|
|
1bd53b6538 | ||
|
|
72455fd3e2 | ||
|
|
964ce8e56d | ||
|
|
d0ed63767b | ||
|
|
1fddbd35b0 | ||
|
|
59af731d48 | ||
|
|
d40539efcf | ||
|
|
6aa75f6954 | ||
|
|
752c9718f9 | ||
|
|
362ddea377 | ||
|
|
90615cab56 | ||
|
|
74d4393c16 | ||
|
|
06c0762b3f | ||
|
|
a45a165b24 | ||
|
|
43c3528b00 | ||
|
|
e6f56172de | ||
|
|
4a047f022e | ||
|
|
9cc3e46314 | ||
|
|
cc711d6a7f | ||
|
|
5b98234fa4 | ||
|
|
5805ff64a8 | ||
|
|
9f2e97e961 | ||
|
|
638f3f9502 | ||
|
|
9920171ba7 | ||
|
|
5aeb66ad30 | ||
|
|
31c306d809 | ||
|
|
3e38adf102 | ||
|
|
d70c3e24e0 | ||
|
|
1e363054d8 | ||
|
|
7219b0134d | ||
|
|
56f3f5fa0a | ||
|
|
22a288834e | ||
|
|
185a465e39 | ||
|
|
574c11ab3f | ||
|
|
f4784e6a1d | ||
|
|
529ca8ef52 | ||
|
|
be3df30fd2 | ||
|
|
1b38a23a53 | ||
|
|
2fc792ba8f | ||
|
|
fcb6f38647 | ||
|
|
35e4a6edc3 | ||
|
|
a61b1fe618 | ||
|
|
e90bccd387 | ||
|
|
fb76871b3f | ||
|
|
748abda567 | ||
|
|
5e2a2977ad | ||
|
|
3f6d7526d7 | ||
|
|
0739756be8 | ||
|
|
39d41e262d | ||
|
|
267daea124 | ||
|
|
463db52e93 | ||
|
|
2b3dfbe488 | ||
|
|
94a229e3f7 | ||
|
|
464b9d4b12 | ||
|
|
e50a851672 | ||
|
|
f853b23370 | ||
|
|
46829fce10 | ||
|
|
fd468f8967 | ||
|
|
d62c81372e | ||
|
|
7cbf4a8817 | ||
|
|
b9cf20973f | ||
|
|
b551ba7f20 | ||
|
|
bd89392bb8 | ||
|
|
c11e709cf4 | ||
|
|
160540487d | ||
|
|
aa622bfdf4 | ||
|
|
a07fbdb415 | ||
|
|
b64ebd5ae7 | ||
|
|
6e9aa8a57e | ||
|
|
5b50da71a4 | ||
|
|
17464ecdb9 | ||
|
|
390dd137a4 | ||
|
|
e150c2f417 | ||
|
|
c93ad88df8 | ||
|
|
95310a785d | ||
|
|
c560efe9c6 | ||
|
|
fc5545731a | ||
|
|
75240a3c4b | ||
|
|
47926b95a9 | ||
|
|
5eb060231f | ||
|
|
276c750ae5 | ||
|
|
3acfad096a | ||
|
|
86762e4164 | ||
|
|
7621c6d489 | ||
|
|
2453823de6 | ||
|
|
fec46643b8 | ||
|
|
a83750fb4a | ||
|
|
f808beece5 | ||
|
|
444e2cce4d | ||
|
|
9bd439a65a | ||
|
|
6a129f58e9 | ||
|
|
e91dffdc92 | ||
|
|
71f6b7c1d8 | ||
|
|
b4ff77b25e | ||
|
|
f8588d3447 | ||
|
|
bb22f7308b | ||
|
|
9c69ca2322 | ||
|
|
53cbe1116e | ||
|
|
54c8f1a66b | ||
|
|
859de0dc44 | ||
|
|
321c6458fc | ||
|
|
d98369b4e1 | ||
|
|
c52da38579 | ||
|
|
0332996f6f | ||
|
|
2fe2828581 | ||
|
|
2e97ccd3e5 | ||
|
|
e5acfbd88e | ||
|
|
706e2b6783 | ||
|
|
f0bf39bc0c | ||
|
|
11228c9936 | ||
|
|
4edf47d84a | ||
|
|
2338f9af99 | ||
|
|
8ccf280b25 | ||
|
|
8c61c9faff | ||
|
|
63e6571485 | ||
|
|
35e721b390 | ||
|
|
7c381879c9 | ||
|
|
bb6abdbefb | ||
|
|
1400d2d19d | ||
|
|
382f9df322 | ||
|
|
b0b9eff5bb | ||
|
|
ae40147eb7 | ||
|
|
20f4bd471e | ||
|
|
78846739ce | ||
|
|
6ab40e6582 | ||
|
|
39865bf3b9 | ||
|
|
03125f866f | ||
|
|
5bc5b344bb | ||
|
|
9fd63f8920 | ||
|
|
8bfc533f21 | ||
|
|
b3045fd830 | ||
|
|
f774f03b40 | ||
|
|
d58dce976c | ||
|
|
4ab0986eeb | ||
|
|
4e65ac7c4e | ||
|
|
d01e6841b9 | ||
|
|
357584ab84 | ||
|
|
c02b920204 | ||
|
|
cf940136f4 | ||
|
|
5fa09a3d75 | ||
|
|
4ba63aef60 | ||
|
|
df4e4dd186 | ||
|
|
2f159f7aa0 | ||
|
|
5e7df90b13 | ||
|
|
2dbbe14922 | ||
|
|
dff55d6599 | ||
|
|
cd111c221f | ||
|
|
9ac3536e31 | ||
|
|
bd5fcd8bc8 | ||
|
|
ea38c9f442 | ||
|
|
66ac5d3ce8 | ||
|
|
38b2346e91 | ||
|
|
b126a0d2a6 | ||
|
|
13128342f2 | ||
|
|
833f14d563 | ||
|
|
2c40fc5563 | ||
|
|
cfbbd2bf44 | ||
|
|
68868d1602 | ||
|
|
300fb6d21a | ||
|
|
c4e0e732bd | ||
|
|
f8efc263db | ||
|
|
df9fb12ae4 | ||
|
|
fdec7dd378 | ||
|
|
63dbb41933 | ||
|
|
d8c51eadaa | ||
|
|
e85c311c90 | ||
|
|
85c41465ab | ||
|
|
0a011dc95e | ||
|
|
cfb951b737 | ||
|
|
63ea3ef99e | ||
|
|
5ad5783920 | ||
|
|
8cf7393f98 | ||
|
|
2766b9b1eb | ||
|
|
5d92b0c38b | ||
|
|
c2edc8d181 | ||
|
|
2df65d402d | ||
|
|
d424fecfbc | ||
|
|
9ab6ce043a | ||
|
|
ebc236309a | ||
|
|
9011226ba9 | ||
|
|
e1c2388cda | ||
|
|
64f84f735b | ||
|
|
2727f09c47 | ||
|
|
3741a47683 | ||
|
|
d6e8e98886 | ||
|
|
fa35c91f89 | ||
|
|
eb482315a0 | ||
|
|
e96c2ecc8c | ||
|
|
2999b38d53 | ||
|
|
5658b6bba9 | ||
|
|
f1632df055 | ||
|
|
0635a02739 | ||
|
|
a26435302e | ||
|
|
ba5d675183 | ||
|
|
0f9f5c8871 | ||
|
|
fc095ba87d | ||
|
|
eb1b2be496 | ||
|
|
c2b9f38189 | ||
|
|
3513a93276 | ||
|
|
e1848bcb3d | ||
|
|
a88ed58534 | ||
|
|
b140962af6 | ||
|
|
6e6865af32 | ||
|
|
7242dfa1d8 | ||
|
|
5f70255432 | ||
|
|
c883e895ba | ||
|
|
1c85a09812 | ||
|
|
6aab168c09 | ||
|
|
ceab9ccba1 | ||
|
|
ded82291ab | ||
|
|
924b53d6a1 | ||
|
|
1fdfac61bd | ||
|
|
420a7d60fb | ||
|
|
58a4f7c43b | ||
|
|
bea79d8f82 | ||
|
|
ec1bc43156 | ||
|
|
3b9fc9e811 | ||
|
|
1c0fbf3382 | ||
|
|
f2b3c5fc92 | ||
|
|
d4896fadce | ||
|
|
810d24fc34 | ||
|
|
ec19cb8097 | ||
|
|
8aa7df51cc | ||
|
|
441f245951 | ||
|
|
38e0db1561 | ||
|
|
34b19b772b | ||
|
|
ab95301c36 | ||
|
|
7c58744a67 | ||
|
|
5e7ca4014f | ||
|
|
aa6f031df4 | ||
|
|
f0a821c493 | ||
|
|
62ad1ee508 | ||
|
|
5887052909 | ||
|
|
dbe33d32aa | ||
|
|
ae03a76592 | ||
|
|
3a9249b4ee | ||
|
|
ec19fcbd20 | ||
|
|
228c054dc6 | ||
|
|
c21758bf11 | ||
|
|
f43998958b | ||
|
|
db3fc0e96a | ||
|
|
939bbe39c0 | ||
|
|
5bb5988601 | ||
|
|
d345984235 | ||
|
|
0340130c5a | ||
|
|
8aaeec9c61 | ||
|
|
ec5fb491a4 | ||
|
|
2a6e65e2fd | ||
|
|
bcf2d9e0ee | ||
|
|
bfc638ce65 | ||
|
|
444c520e31 | ||
|
|
9821e87349 | ||
|
|
f9d9adbe17 | ||
|
|
8c04ac3c91 | ||
|
|
dd897a78c6 | ||
|
|
1835ca5f03 | ||
|
|
1decf414b0 | ||
|
|
4ee2199ea9 | ||
|
|
5d015feb39 | ||
|
|
0793148e77 | ||
|
|
8d70f77268 | ||
|
|
6f9adc5d5c | ||
|
|
bf7ce66466 | ||
|
|
7289ed5437 | ||
|
|
56d9da48a9 | ||
|
|
c8ea1e5da2 | ||
|
|
2805282a16 | ||
|
|
bec0337316 | ||
|
|
2d0d2311d3 | ||
|
|
8216512c8e | ||
|
|
8eda7c5277 | ||
|
|
2b8c75323d | ||
|
|
ab14459373 | ||
|
|
f32ff85bc3 | ||
|
|
b86d49bcf4 | ||
|
|
e108f0dfab | ||
|
|
a84ebc59c1 | ||
|
|
d114ceee6d | ||
|
|
7d94cdaf66 | ||
|
|
2ded466c2a | ||
|
|
e00289a268 | ||
|
|
08cb8d2121 | ||
|
|
e65d075083 | ||
|
|
8d6b2335df | ||
|
|
df9967323e | ||
|
|
1368b08875 | ||
|
|
476369f600 | ||
|
|
d59cf5aa65 | ||
|
|
ec3bcb46e0 | ||
|
|
f1ad45f513 | ||
|
|
de18ca9888 | ||
|
|
17526e5c52 | ||
|
|
0da204ab11 | ||
|
|
c9b5cf5910 | ||
|
|
50716e1959 | ||
|
|
30ca142b35 | ||
|
|
7f4314ca47 | ||
|
|
88ca4fcf98 | ||
|
|
82b57a9740 | ||
|
|
0646e21c6f | ||
|
|
076a050bbf | ||
|
|
c359384806 | ||
|
|
7f53fce04e | ||
|
|
ed84daf889 | ||
|
|
82e31ba4a9 | ||
|
|
200ae00a12 | ||
|
|
78731e288a | ||
|
|
400abd1d7f | ||
|
|
94817fa277 | ||
|
|
7c0980ee6c | ||
|
|
e3cb54b42b | ||
|
|
53e8522453 | ||
|
|
a6d47272af | ||
|
|
dc6ea847e1 | ||
|
|
ec91352d64 | ||
|
|
1b5e6d4aed | ||
|
|
927dd43020 | ||
|
|
8055fbd321 | ||
|
|
044dd73668 | ||
|
|
af9e8bf368 | ||
|
|
f162db9618 | ||
|
|
53d2bc4f89 | ||
|
|
44681dd67f | ||
|
|
ab5ae538f6 | ||
|
|
12c8b3f895 | ||
|
|
5797a13c1f | ||
|
|
31b219bffa | ||
|
|
10ab6874cb | ||
|
|
a4a65701f4 | ||
|
|
45849e410b | ||
|
|
80815b7a18 | ||
|
|
51b5ac2f11 | ||
|
|
dabc205b20 | ||
|
|
de09764140 | ||
|
|
1f27094c78 | ||
|
|
57168d660b | ||
|
|
1cab1650fd | ||
|
|
dafb79b967 | ||
|
|
bb6b6d20cf | ||
|
|
7a15e83449 | ||
|
|
42371f7236 | ||
|
|
0c491a75ca | ||
|
|
f75fb1a13f | ||
|
|
affb84375d | ||
|
|
2aaa3389d1 | ||
|
|
0d32537a91 | ||
|
|
7278794021 | ||
|
|
0fadc61d5b | ||
|
|
f0020dcb21 | ||
|
|
7a32f7f9b1 | ||
|
|
a7a864bc1b | ||
|
|
56914db37f | ||
|
|
9525f90ca4 | ||
|
|
7a0b0caea1 | ||
|
|
bc2fcdafce | ||
|
|
14de0d62d3 | ||
|
|
8e1092726c | ||
|
|
94208dc524 | ||
|
|
6050823986 | ||
|
|
95a8adc7e5 | ||
|
|
3e718bf2d4 | ||
|
|
0dc4f71fcb | ||
|
|
b92f70d190 | ||
|
|
ab1d9a37eb | ||
|
|
119aec5306 | ||
|
|
ebbd18c365 | ||
|
|
6445be4ea6 | ||
|
|
30e662a0a5 | ||
|
|
66b380ed5a | ||
|
|
ad4d2eefa8 | ||
|
|
8a3cdd71cb | ||
|
|
22ef0ee13e | ||
|
|
4937278516 | ||
|
|
97a48a0d79 | ||
|
|
53c7eb8adf | ||
|
|
70ff28fcf0 |
No files matched your search
-44
@@ -1,44 +0,0 @@
|
||||
env:
|
||||
CIRRUS_CLONE_DEPTH: 1
|
||||
ARCH: amd64
|
||||
|
||||
FreeBSD_task:
|
||||
matrix:
|
||||
env:
|
||||
BS: autotools
|
||||
env:
|
||||
BS: cmake
|
||||
matrix:
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-2
|
||||
freebsd_instance:
|
||||
image_family: freebsd-13-5
|
||||
prepare_script:
|
||||
- ./build/ci/cirrus_ci/ci.sh prepare
|
||||
configure_script:
|
||||
- env CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a autogen
|
||||
- env CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a configure
|
||||
build_script:
|
||||
- env MAKE_ARGS="-j 2" ./build/ci/build.sh -a build
|
||||
test_script:
|
||||
- env SKIP_TEST_RESTORE_ATIME=1 MAKE_ARGS="-j 2" ./build/ci/build.sh -a test
|
||||
- ./build/ci/cirrus_ci/ci.sh test
|
||||
install_script:
|
||||
- env MAKE_ARGS="-j 2" ./build/ci/build.sh -a install
|
||||
|
||||
Windows_Cygwin_task:
|
||||
windows_container:
|
||||
image: cirrusci/windowsservercore:2019
|
||||
os_version: 2019
|
||||
env:
|
||||
BE: cygwin-gcc
|
||||
prepare_script:
|
||||
- build\ci\cirrus_ci\ci.cmd prepare
|
||||
configure_script:
|
||||
- build\ci\cirrus_ci\ci.cmd configure
|
||||
build_script:
|
||||
- build\ci\cirrus_ci\ci.cmd build
|
||||
test_script:
|
||||
- build\ci\cirrus_ci\ci.cmd test
|
||||
install_script:
|
||||
- build\ci\cirrus_ci\ci.cmd install
|
||||
+57
-18
@@ -6,13 +6,34 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
FreeBSD:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
bs: [autotools, cmake]
|
||||
steps:
|
||||
- name: Build and test on a FreeBSD 15 firecracker VM
|
||||
uses: acj/freebsd-firecracker-action@e04896d2dd91f7ec7381e5f363c6fbe83ee445c3 # v0.11.0
|
||||
with:
|
||||
run-in-vm: |
|
||||
chflags -R noschg / && \
|
||||
fetch -o - https://download.freebsd.org/releases/amd64/15.0-RELEASE/base.txz | bsdtar -x -C / -f - && \
|
||||
pkg bootstrap -y && \
|
||||
cd firecracker-freebsd && \
|
||||
env BS=${{ matrix.bs }} ./build/ci/github_actions/freebsd.sh prepare && \
|
||||
env BS=${{ matrix.bs }} CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a autogen && \
|
||||
env BS=${{ matrix.bs }} MAKE=gmake CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./build/ci/build.sh -a configure && \
|
||||
env BS=${{ matrix.bs }} MAKE=gmake MAKE_ARGS="-j 2" ./build/ci/build.sh -a build && \
|
||||
env BS=${{ matrix.bs }} MAKE=gmake SKIP_TEST_RESTORE_ATIME=1 MAKE_ARGS="-j 2" ./build/ci/build.sh -a test && \
|
||||
env BS=${{ matrix.bs }} ./build/ci/github_actions/freebsd.sh test && \
|
||||
env BS=${{ matrix.bs }} MAKE=gmake MAKE_ARGS="-j 2" ./build/ci/build.sh -a install
|
||||
MacOS:
|
||||
runs-on: macos-15
|
||||
strategy:
|
||||
matrix:
|
||||
bs: [autotools, cmake]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install dependencies
|
||||
run: ./build/ci/github_actions/install-macos-dependencies.sh
|
||||
- name: Autogen
|
||||
@@ -47,7 +68,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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: libarchive-macos-${{ matrix.bs }}-${{ github.sha }}
|
||||
path: libarchive.tar.xz
|
||||
@@ -59,7 +80,7 @@ jobs:
|
||||
bs: [autotools, cmake]
|
||||
crypto: [mbedtls, nettle, openssl]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Update apt cache
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
@@ -93,14 +114,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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Update package definitions
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
@@ -115,7 +136,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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: libarchive-${{ github.sha }}
|
||||
path: libarchive-dist.tar
|
||||
@@ -125,18 +146,36 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
be: [mingw-gcc, msvc]
|
||||
be: [mingw-gcc, cygwin-gcc, msvc]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- name: Install mingw
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Cygwin
|
||||
uses: cygwin/cygwin-install-action@3f0a3f9f988f7e96b8c18098ae05eaec175f5b52 # v6
|
||||
if: ${{ matrix.be=='cygwin-gcc' }}
|
||||
with:
|
||||
install-dir: "D:\\cygwin"
|
||||
packages: |-
|
||||
make autoconf automake cmake
|
||||
gcc-core binutils libtool pkg-config
|
||||
bison zlib-devel libbz2-devel liblzma-devel
|
||||
liblz4-devel libiconv-devel libxml2-devel
|
||||
libzstd-devel libssl-devel
|
||||
- name: Install MinGW (msys2)
|
||||
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
||||
if: ${{ matrix.be=='mingw-gcc' }}
|
||||
run: choco install mingw
|
||||
shell: cmd
|
||||
- name: Install library dependencies
|
||||
run: ./build/ci/github_actions/ci.cmd deplibs
|
||||
shell: cmd
|
||||
env:
|
||||
BE: ${{ matrix.be }}
|
||||
with:
|
||||
location: "D:\\"
|
||||
install: |-
|
||||
mingw-w64-x86_64-gcc
|
||||
mingw-w64-x86_64-autotools
|
||||
mingw-w64-x86_64-binutils
|
||||
mingw-w64-x86_64-pkgconf
|
||||
mingw-w64-x86_64-cmake
|
||||
mingw-w64-x86_64-make
|
||||
mingw-w64-x86_64-zlib
|
||||
mingw-w64-x86_64-bzip2
|
||||
mingw-w64-x86_64-xz
|
||||
mingw-w64-x86_64-zstd
|
||||
- name: Configure
|
||||
run: ./build/ci/github_actions/ci.cmd configure
|
||||
shell: cmd
|
||||
@@ -163,7 +202,7 @@ jobs:
|
||||
shell: cmd
|
||||
env:
|
||||
BE: ${{ matrix.be }}
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: libarchive-windows-${{ matrix.be }}-${{ github.sha }}
|
||||
path: libarchive.zip
|
||||
path: ${{ matrix.be=='cygwin-gcc' && 'libarchive.tar.xz' || 'libarchive.zip' }}
|
||||
@@ -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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: failure() && steps.build.outcome == 'success'
|
||||
with:
|
||||
name: artifacts
|
||||
|
||||
@@ -26,18 +26,18 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
uses: github/codeql-action/autobuild@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
@@ -0,0 +1,34 @@
|
||||
name: Lint
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
Lint:
|
||||
runs-on: ubuntu-26.04
|
||||
env:
|
||||
BS: cmake
|
||||
CRYPTO: openssl
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Update apt cache
|
||||
run: sudo apt-get update
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y autoconf automake build-essential cmake git libssl-dev nettle-dev libmbedtls-dev libacl1-dev libbz2-dev liblzma-dev liblz4-dev libzstd-dev lzop pkg-config zlib1g-dev libclang-22-dev libclang-cpp22-dev clang-22 ninja-build
|
||||
- name: Install Lint
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
cmake -S build/la-lint -B /tmp/lint-build -GNinja
|
||||
cmake --build /tmp/lint-build
|
||||
cmake --install /tmp/lint-build
|
||||
- name: Configure
|
||||
run: ./build/ci/build.sh -a configure
|
||||
env:
|
||||
CMAKE_ARGS: -GNinja -DENABLE_CLANG_TIDY=YES -DCLANG_TIDY_PATH=la-lint
|
||||
- name: Build
|
||||
run: ./build/ci/build.sh -a build
|
||||
env:
|
||||
MAKE: ninja
|
||||
MAKE_ARGS: --
|
||||
@@ -29,12 +29,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -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@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
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@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
|
||||
uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
+10
-3
@@ -9,6 +9,7 @@
|
||||
*.lo
|
||||
*.recipe
|
||||
*.sln
|
||||
*.slnx
|
||||
*.tlog
|
||||
*.cmake
|
||||
*.vcxproj
|
||||
@@ -27,6 +28,8 @@ bsdcat
|
||||
bsdcpio
|
||||
bsdtar
|
||||
bsdunzip
|
||||
build/.ninja_deps
|
||||
build/.ninja_log
|
||||
build/autoconf/compile
|
||||
build/autoconf/config.guess
|
||||
build/autoconf/config.sub
|
||||
@@ -39,8 +42,10 @@ build/autoconf/ltsugar.m4
|
||||
build/autoconf/ltversion.m4
|
||||
build/autoconf/lt~obsolete.m4
|
||||
build/autoconf/missing
|
||||
build/build.ninja
|
||||
build/build/pkgconfig/libarchive.pc
|
||||
build/cat/test/list.h
|
||||
build/compile_commands.json
|
||||
build/cpio/test/list.h
|
||||
build/libarchive/test/list.h
|
||||
build/pkgconfig/libarchive.pc
|
||||
@@ -59,6 +64,8 @@ libtool
|
||||
stamp-h1
|
||||
tar/test/list.h
|
||||
unzip/test/list.h
|
||||
CLAUDE.md
|
||||
GEMINI.md
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
DartConfiguration.tcl
|
||||
@@ -80,9 +87,9 @@ libarchive-*.tar.gz
|
||||
libarchive-*.zip
|
||||
|
||||
Testing/
|
||||
libarchive/libarchive.a
|
||||
libarchive/libarchive.so
|
||||
libarchive/libarchive.so.*
|
||||
**/libarchive/libarchive.a
|
||||
**/libarchive/libarchive.so
|
||||
**/libarchive/libarchive.so.*
|
||||
|
||||
.DS_Store
|
||||
|
||||
|
||||
+130
-125
@@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.17 FATAL_ERROR)
|
||||
|
||||
PROJECT(libarchive C)
|
||||
#
|
||||
# Include standard installation directories
|
||||
include(GNUInstallDirs)
|
||||
#
|
||||
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake")
|
||||
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${libarchive_BINARY_DIR}/bin)
|
||||
@@ -16,7 +19,7 @@ endif()
|
||||
# MinSizeRel : Release Min Size build
|
||||
# None : No build type
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Build Type" FORCE)
|
||||
SET(CMAKE_BUILD_TYPE "Release" 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".
|
||||
@@ -136,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")
|
||||
@@ -145,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$")
|
||||
@@ -241,19 +246,19 @@ OPTION(ENABLE_CPIO "Enable cpio building" ON)
|
||||
OPTION(ENABLE_CPIO_SHARED "Enable dynamic build of cpio" FALSE)
|
||||
OPTION(ENABLE_CAT "Enable cat building" ON)
|
||||
OPTION(ENABLE_CAT_SHARED "Enable dynamic build of cat" FALSE)
|
||||
IF(WIN32 AND NOT CYGWIN)
|
||||
SET(ENABLE_UNZIP FALSE)
|
||||
SET(ENABLE_UNZIP_SHARED FALSE)
|
||||
ELSE()
|
||||
OPTION(ENABLE_UNZIP "Enable unzip building" ON)
|
||||
OPTION(ENABLE_UNZIP_SHARED "Enable dynamic build of unzip" FALSE)
|
||||
ENDIF()
|
||||
OPTION(ENABLE_XATTR "Enable extended attribute support" ON)
|
||||
OPTION(ENABLE_ACL "Enable ACL support" ON)
|
||||
OPTION(ENABLE_ICONV "Enable iconv support" ON)
|
||||
OPTION(ENABLE_TEST "Enable unit and regression tests" ON)
|
||||
OPTION(ENABLE_COVERAGE "Enable code coverage (GCC only, automatically sets ENABLE_TEST to ON)" FALSE)
|
||||
OPTION(ENABLE_INSTALL "Enable installing of libraries" ON)
|
||||
OPTION(ENABLE_CLANG_TIDY "Enable custom build-time code health checks" OFF)
|
||||
|
||||
IF(WIN32 AND MSVC)
|
||||
OPTION(MSVC_USE_STATIC_CRT "Use static CRT" OFF)
|
||||
ENDIF()
|
||||
|
||||
SET(POSIX_REGEX_LIB "AUTO" CACHE STRING "Choose what library should provide POSIX regular expression support")
|
||||
SET(ENABLE_SAFESEH "AUTO" CACHE STRING "Enable use of /SAFESEH linker flag (MSVC only)")
|
||||
@@ -332,27 +337,69 @@ INCLUDE(CheckTypeSize)
|
||||
#
|
||||
# Generate list.h
|
||||
#
|
||||
MACRO (GENERATE_LIST_H _listfile _cmlist __list_sources)
|
||||
MACRO (GENERATE_LIST_H _listfile _cmlist _target __list_sources)
|
||||
SET(_argv ${ARGV})
|
||||
# Remove _listfile and _cmlist from _argv
|
||||
LIST(REMOVE_AT _argv 0 1)
|
||||
IF (NOT EXISTS "${_listfile}" OR
|
||||
${_cmlist} IS_NEWER_THAN "${_listfile}")
|
||||
|
||||
MESSAGE(STATUS "Generating ${_listfile}")
|
||||
FILE(WRITE ${_listfile} "")
|
||||
FOREACH (testfile ${_argv})
|
||||
IF (testfile MATCHES "^test_[^/]+[.]c$")
|
||||
FILE(STRINGS ${testfile} testvar REGEX "^DEFINE_TEST")
|
||||
FOREACH (deftest ${testvar})
|
||||
FILE(APPEND ${_listfile} "${deftest}\n")
|
||||
ENDFOREACH (deftest)
|
||||
ENDIF (testfile MATCHES "^test_[^/]+[.]c$")
|
||||
ENDFOREACH (testfile)
|
||||
|
||||
ENDIF (NOT EXISTS "${_listfile}" OR
|
||||
${_cmlist} IS_NEWER_THAN "${_listfile}")
|
||||
# Remove _listfile, _cmlist, and _target from _argv
|
||||
LIST(REMOVE_AT _argv 0 1 2)
|
||||
# Convert source paths to absolute so discover_tests.cmake can find them
|
||||
# regardless of the working directory when cmake -P runs.
|
||||
SET(_gl_abs_sources "")
|
||||
FOREACH(_gl_src ${_argv})
|
||||
IF(IS_ABSOLUTE "${_gl_src}")
|
||||
LIST(APPEND _gl_abs_sources "${_gl_src}")
|
||||
ELSE()
|
||||
LIST(APPEND _gl_abs_sources "${CMAKE_CURRENT_SOURCE_DIR}/${_gl_src}")
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
# Stamp out discover_tests.cmake with source list and output path baked in.
|
||||
SET(SOURCES "${_gl_abs_sources}")
|
||||
SET(OUTPUT "${_listfile}")
|
||||
CONFIGURE_FILE(
|
||||
${CMAKE_SOURCE_DIR}/build/cmake/discover_tests.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/discover_tests.cmake
|
||||
@ONLY)
|
||||
UNSET(SOURCES)
|
||||
UNSET(OUTPUT)
|
||||
# list.h is regenerated at build time whenever any test .c file changes.
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT "${_listfile}"
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/discover_tests.cmake
|
||||
DEPENDS ${_gl_abs_sources}
|
||||
COMMENT "Generating ${_listfile}"
|
||||
VERBATIM)
|
||||
# Attaching list.h to the target tells CMake to build it before compiling.
|
||||
TARGET_SOURCES(${_target} PRIVATE "${_listfile}")
|
||||
ENDMACRO (GENERATE_LIST_H)
|
||||
|
||||
#
|
||||
# Register individual tests with CTest by scanning DEFINE_TEST() declarations.
|
||||
#
|
||||
MACRO (DISCOVER_TESTS _component __list_sources)
|
||||
IF(ENABLE_TEST)
|
||||
SET(_sources ${ARGV})
|
||||
LIST(REMOVE_AT _sources 0)
|
||||
FOREACH (_src ${_sources})
|
||||
IF (_src MATCHES "test_[^/]+\\.c$")
|
||||
FILE(STRINGS "${_src}" _lines REGEX "^DEFINE_TEST\(.*\)")
|
||||
FOREACH (_line ${_lines})
|
||||
STRING(REGEX MATCH "DEFINE_TEST\((.*)\)" _full_match ${_line})
|
||||
# CMake REGEX seems to handle ( and \( rather inconsistently...
|
||||
# So we go through an extra dance to definitively strip the parens
|
||||
STRING(REPLACE "(" "" _test_name_with_paren "${CMAKE_MATCH_1}")
|
||||
STRING(REPLACE ")" "" _test_name "${_test_name_with_paren}")
|
||||
SET(_full_test_name "${_component}_${_test_name}")
|
||||
ADD_TEST(NAME ${_full_test_name}
|
||||
COMMAND ${_component}_test -vv
|
||||
-r ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-s
|
||||
${_test_name})
|
||||
SET_TESTS_PROPERTIES(${_full_test_name} PROPERTIES SKIP_RETURN_CODE 2)
|
||||
ENDFOREACH (_line)
|
||||
ENDIF (_src MATCHES "test_[^/]+\\.c$")
|
||||
ENDFOREACH (_src)
|
||||
ENDIF(ENABLE_TEST)
|
||||
ENDMACRO (DISCOVER_TESTS __list_sources)
|
||||
|
||||
#
|
||||
# Generate installation rules for man pages.
|
||||
#
|
||||
@@ -654,7 +701,7 @@ IF(ENABLE_ZSTD)
|
||||
ENDIF()
|
||||
|
||||
FIND_PATH(ZSTD_INCLUDE_DIR zstd.h HINTS ${PC_ZSTD_INCLUDEDIR} ${PC_ZSTD_INCLUDE_DIRS})
|
||||
FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS})
|
||||
FIND_LIBRARY(ZSTD_LIBRARY NAMES zstd libzstd zstd_static HINTS ${PC_ZSTD_LIBDIR} ${PC_ZSTD_LIBRARY_DIRS})
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(ZSTD DEFAULT_MSG ZSTD_LIBRARY ZSTD_INCLUDE_DIR)
|
||||
ELSE(ENABLE_ZSTD)
|
||||
@@ -723,6 +770,7 @@ CHECK_C_SOURCE_COMPILES("#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
int main(void) { return FS_IOC_GETFLAGS; }" HAVE_WORKING_FS_IOC_GETFLAGS)
|
||||
|
||||
LA_CHECK_INCLUDE_FILE("intsafe.h" HAVE_INTSAFE_H)
|
||||
LA_CHECK_INCLUDE_FILE("linux/magic.h" HAVE_LINUX_MAGIC_H)
|
||||
LA_CHECK_INCLUDE_FILE("locale.h" HAVE_LOCALE_H)
|
||||
LA_CHECK_INCLUDE_FILE("membership.h" HAVE_MEMBERSHIP_H)
|
||||
@@ -737,7 +785,9 @@ LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
|
||||
LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
|
||||
LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
|
||||
LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
|
||||
LA_CHECK_INCLUDE_FILE("stdckdint.h" HAVE_STDCKDINT_H)
|
||||
LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
|
||||
LA_CHECK_INCLUDE_FILE("stdio.h" HAVE_STDIO_H)
|
||||
LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
|
||||
LA_CHECK_INCLUDE_FILE("string.h" HAVE_STRING_H)
|
||||
LA_CHECK_INCLUDE_FILE("strings.h" HAVE_STRINGS_H)
|
||||
@@ -771,12 +821,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)
|
||||
|
||||
#
|
||||
@@ -804,11 +864,14 @@ IF(ENABLE_MBEDTLS)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${MBEDCRYPTO_LIBRARY})
|
||||
INCLUDE_DIRECTORIES(${MBEDTLS_INCLUDE_DIRS})
|
||||
|
||||
CMAKE_PUSH_CHECK_STATE()
|
||||
LIST(APPEND CMAKE_REQUIRED_INCLUDES ${MBEDTLS_INCLUDE_DIRS})
|
||||
LA_CHECK_INCLUDE_FILE("mbedtls/aes.h" HAVE_MBEDTLS_AES_H)
|
||||
LA_CHECK_INCLUDE_FILE("mbedtls/md.h" HAVE_MBEDTLS_MD_H)
|
||||
LA_CHECK_INCLUDE_FILE("mbedtls/pkcs5.h" HAVE_MBEDTLS_PKCS5_H)
|
||||
LA_CHECK_INCLUDE_FILE("mbedtls/version.h" HAVE_MBEDTLS_VERSION_H)
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
|
||||
ENDIF(MBEDTLS_FOUND)
|
||||
MARK_AS_ADVANCED(CLEAR MBEDTLS_INCLUDE_DIRS)
|
||||
MARK_AS_ADVANCED(CLEAR MBEDCRYPTO_LIBRARY)
|
||||
@@ -824,6 +887,7 @@ IF(ENABLE_NETTLE)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${NETTLE_LIBRARIES})
|
||||
INCLUDE_DIRECTORIES(${NETTLE_INCLUDE_DIR})
|
||||
|
||||
CMAKE_PUSH_CHECK_STATE()
|
||||
LIST(APPEND CMAKE_REQUIRED_INCLUDES ${NETTLE_INCLUDE_DIR})
|
||||
LA_CHECK_INCLUDE_FILE("nettle/aes.h" HAVE_NETTLE_AES_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/hmac.h" HAVE_NETTLE_HMAC_H)
|
||||
@@ -832,6 +896,8 @@ IF(ENABLE_NETTLE)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/ripemd160.h" HAVE_NETTLE_RIPEMD160_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/sha.h" HAVE_NETTLE_SHA_H)
|
||||
LA_CHECK_INCLUDE_FILE("nettle/version.h" HAVE_NETTLE_VERSION_H)
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
|
||||
ENDIF(NETTLE_FOUND)
|
||||
MARK_AS_ADVANCED(CLEAR NETTLE_INCLUDE_DIR)
|
||||
MARK_AS_ADVANCED(CLEAR NETTLE_LIBRARIES)
|
||||
@@ -847,11 +913,15 @@ IF(ENABLE_OPENSSL AND NOT CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
SET(HAVE_LIBCRYPTO 1)
|
||||
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
|
||||
LIST(APPEND ADDITIONAL_LIBS ${OPENSSL_CRYPTO_LIBRARY})
|
||||
|
||||
CMAKE_PUSH_CHECK_STATE()
|
||||
SET(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
LA_CHECK_INCLUDE_FILE("openssl/evp.h" HAVE_OPENSSL_EVP_H)
|
||||
LA_CHECK_INCLUDE_FILE("openssl/opensslv.h" HAVE_OPENSSL_OPENSSLV_H)
|
||||
CHECK_FUNCTION_EXISTS(PKCS5_PBKDF2_HMAC_SHA1 HAVE_PKCS5_PBKDF2_HMAC_SHA1)
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
|
||||
ENDIF(OPENSSL_FOUND)
|
||||
ELSE()
|
||||
SET(OPENSSL_FOUND FALSE) # Override cached value
|
||||
@@ -872,9 +942,13 @@ ENDIF(NOT OPENSSL_FOUND)
|
||||
# libbsd for readpassphrase on Haiku
|
||||
IF("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku")
|
||||
MESSAGE(STATUS "Adding libbsd for Haiku")
|
||||
|
||||
CMAKE_PUSH_CHECK_STATE()
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "bsd")
|
||||
FIND_LIBRARY(LIBBSD_LIBRARY NAMES bsd)
|
||||
LIST(APPEND ADDITIONAL_LIBS ${LIBBSD_LIBRARY})
|
||||
CMAKE_POP_CHECK_STATE()
|
||||
|
||||
ENDIF("${CMAKE_SYSTEM_NAME}" MATCHES "Haiku")
|
||||
|
||||
#
|
||||
@@ -985,85 +1059,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 **
|
||||
@@ -1078,8 +1073,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
|
||||
@@ -1257,7 +1252,7 @@ ELSE(LIBXML2_FOUND)
|
||||
# Check linkage as well; versions of mingw-w64 before v11.0.0
|
||||
# do not contain an import library for xmllite.
|
||||
cmake_push_check_state()
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "xmllite")
|
||||
SET(CMAKE_REQUIRED_LIBRARIES "xmllite" "uuid")
|
||||
check_c_source_compiles("
|
||||
#include <initguid.h>
|
||||
#include <xmllite.h>
|
||||
@@ -1268,7 +1263,7 @@ ELSE(LIBXML2_FOUND)
|
||||
cmake_pop_check_state()
|
||||
IF(HAVE_XMLLITE_H)
|
||||
SET(XMLLITE_FOUND TRUE)
|
||||
LIST(APPEND ADDITIONAL_LIBS "xmllite")
|
||||
LIST(APPEND ADDITIONAL_LIBS "xmllite" "uuid")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF(EXPAT_FOUND)
|
||||
@@ -1472,6 +1467,8 @@ CHECK_FUNCTION_EXISTS_GLIBC(arc4random_buf HAVE_ARC4RANDOM_BUF)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(chflags HAVE_CHFLAGS)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(chown HAVE_CHOWN)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(chroot HAVE_CHROOT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(closefrom HAVE_CLOSEFROM)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(close_range HAVE_CLOSE_RANGE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(ctime_r HAVE_CTIME_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(fchdir HAVE_FCHDIR)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(fchflags HAVE_FCHFLAGS)
|
||||
@@ -1489,15 +1486,20 @@ CHECK_FUNCTION_EXISTS_GLIBC(ftruncate HAVE_FTRUNCATE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(futimens HAVE_FUTIMENS)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(futimes HAVE_FUTIMES)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(futimesat HAVE_FUTIMESAT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getegid HAVE_GETEGID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(geteuid HAVE_GETEUID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getgrgid_r HAVE_GETGRGID_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getgrnam_r HAVE_GETGRNAM_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getline HAVE_GETLINE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getpwnam_r HAVE_GETPWNAM_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getpwuid_r HAVE_GETPWUID_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getpid HAVE_GETPID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getresgid HAVE_GETRESGID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getresuid HAVE_GETRESUID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(gettimeofday HAVE_GETTIMEOFDAY)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(getvfsbyname HAVE_GETVFSBYNAME)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(gmtime_r HAVE_GMTIME_R)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(issetugid HAVE_ISSETUGID)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(lchflags HAVE_LCHFLAGS)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(lchmod HAVE_LCHMOD)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(lchown HAVE_LCHOWN)
|
||||
@@ -1516,6 +1518,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawn HAVE_POSIX_SPAWN)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
|
||||
CHECK_FUNCTION_EXISTS_GLIBC(readpassphrase HAVE_READPASSPHRASE)
|
||||
@@ -1579,12 +1582,6 @@ CHECK_C_SOURCE_COMPILES(
|
||||
"#include <sys/types.h>\n#include <sys/mount.h>\nint main(void) { struct statfs s; return sizeof(s);}"
|
||||
HAVE_STRUCT_STATFS)
|
||||
|
||||
# Make sure we have the POSIX version of readdir_r, not the
|
||||
# older 2-argument version.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); struct dirent e,*r; return readdir_r(d,&e,&r);}"
|
||||
HAVE_READDIR_R)
|
||||
|
||||
# dirfd can be either a function or a macro.
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#include <dirent.h>\nint main() {DIR *d = opendir(\".\"); return dirfd(d);}"
|
||||
@@ -2165,18 +2162,19 @@ ENDIF(ENABLE_ACL)
|
||||
# Check MD5/RMD160/SHA support
|
||||
# NOTE: Crypto checks must be run last before generating config.h
|
||||
#
|
||||
IF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM)
|
||||
ELSE()
|
||||
CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" LIBC)
|
||||
CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC2)
|
||||
CHECK_CRYPTO("SHA256;SHA384;SHA512" LIBC3)
|
||||
CHECK_CRYPTO("MD5;SHA1;SHA256;SHA384;SHA512" LIBSYSTEM)
|
||||
CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" MBEDTLS)
|
||||
CHECK_CRYPTO("MD5;RMD160;SHA1;SHA256;SHA384;SHA512" NETTLE)
|
||||
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")
|
||||
ENDIF()
|
||||
|
||||
# Check visibility annotations
|
||||
SET(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
@@ -2232,6 +2230,13 @@ IF(ENABLE_TEST)
|
||||
ADD_CUSTOM_TARGET(run_all_tests)
|
||||
ENDIF(ENABLE_TEST)
|
||||
|
||||
IF(ENABLE_CLANG_TIDY)
|
||||
IF(NOT CLANG_TIDY_PATH)
|
||||
SET(CLANG_TIDY_PATH clang-tidy)
|
||||
ENDIF(NOT CLANG_TIDY_PATH)
|
||||
SET(CMAKE_C_CLANG_TIDY ${CLANG_TIDY_PATH})
|
||||
ENDIF(ENABLE_CLANG_TIDY)
|
||||
|
||||
add_subdirectory(libarchive)
|
||||
add_subdirectory(cat)
|
||||
add_subdirectory(tar)
|
||||
|
||||
+310
-105
File diff suppressed because it is too large.
Load diff
@@ -1,3 +1,31 @@
|
||||
Jul 28, 2026: libarchive 3.8.9 released
|
||||
|
||||
Jun 23, 2026: libarchive 3.8.8 released
|
||||
|
||||
Apr 13, 2026: libarchive 3.8.7 released
|
||||
|
||||
Mar 10, 2026: libarchive 3.8.6 released
|
||||
|
||||
Jan 05, 2026: libarchive 3.8.5 released
|
||||
|
||||
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
|
||||
|
||||
Mar 20, 2025: libarchive 3.7.8 released
|
||||
|
||||
Oct 13, 2024: libarchive 3.7.7 released
|
||||
|
||||
Sep 23, 2024: libarchive 3.7.6 released
|
||||
|
||||
Sep 13, 2024: libarchive 3.7.5 released
|
||||
|
||||
Apr 26, 2024: libarchive 3.7.4 released
|
||||
|
||||
@@ -37,10 +37,13 @@ The top-level directory contains the following information files:
|
||||
* **CMakeLists.txt** - input for "cmake" build tool, see INSTALL
|
||||
* **configure** - configuration script, see INSTALL for details. If your copy of the source lacks a `configure` script, you can try to construct it by running the script in `build/autogen.sh` (or use `cmake`).
|
||||
|
||||
The following files in the top-level directory are used by the 'configure' script:
|
||||
The following files in the top-level directory are related to the 'configure' script and are only needed by maintainers:
|
||||
|
||||
* `Makefile.am`, `aclocal.m4`, `configure.ac` - used to build this distribution, only needed by maintainers
|
||||
* `Makefile.in`, `config.h.in` - templates used by configure script
|
||||
* `configure.ac` - used (by autoconf) to build the configure script and related files
|
||||
* `Makefile.am` - used (by automake) to generate Makefile.in
|
||||
* `aclocal.m4` - auto-generated file (created by aclocal) used to build the configure script
|
||||
* `Makefile.in` - auto-generated template (created by automake) used by the configure script to create Makefile
|
||||
* `config.h.in` - auto-generated template (created by autoheader) used by the configure script to create config.h
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -191,7 +194,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 +217,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.
|
||||
|
||||
+13
-6
@@ -1,9 +1,10 @@
|
||||
# Security Policy
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it
|
||||
privately. **Do not disclose it as a public issue.** This gives us time to work with you
|
||||
to fix the issue before public exposure, reducing the chance that the exploit will be
|
||||
used before a patch is released.
|
||||
If you have discovered a security vulnerability in this project,
|
||||
please report it privately.
|
||||
**Do not disclose it as a public issue.**
|
||||
This gives us time to work with you to fix the issue before public exposure,
|
||||
reducing the chance that the exploit will be used before a patch is released.
|
||||
|
||||
You may submit the report in the following ways:
|
||||
|
||||
@@ -15,5 +16,11 @@ Please provide the following information in your report:
|
||||
- A description of the vulnerability and its impact
|
||||
- How to reproduce the issue
|
||||
|
||||
This project is maintained by volunteers on a reasonable-effort basis. As such, we ask
|
||||
that you give me 90 days to work on a fix before public exposure.
|
||||
While we welcome all reports, we can act most quickly if the report
|
||||
includes a complete libarchive test case and a proposed fix.
|
||||
See [doc/WRITING_TESTS.md](doc/WRITING_TESTS.md) for guidance on creating a reproduction test case.
|
||||
You can provide the test case and proposed fix as separate patch files
|
||||
prepared with `git format-patch` or `git diff`.
|
||||
|
||||
This project is maintained by volunteers on a reasonable-effort basis.
|
||||
We ask that you give us 90 days to work on a fix before public exposure.
|
||||
@@ -1,4 +0,0 @@
|
||||
FROM cirrusci/windowsservercore:2019
|
||||
|
||||
RUN choco install -y --no-progress cygwin
|
||||
RUN C:\tools\cygwin\cygwinsetup.exe -q -P make,autoconf,automake,cmake,gcc-core,binutils,libtool,pkg-config,bison,zlib-devel,libbz2-devel,liblzma-devel,liblz4-devel,libiconv-devel,libxml2-devel,libzstd-devel,libssl-devel
|
||||
@@ -1,3 +0,0 @@
|
||||
FROM fedora:31
|
||||
|
||||
RUN dnf -y install make cmake gcc gcc-c++ kernel-devel automake libtool bison pkgconf libacl-devel libasan librichacl-devel bzip2-devel zlib-devel xz-devel lz4-devel libzstd-devel openssl-devel nettle-devel mbedtls-devel
|
||||
@@ -1,3 +0,0 @@
|
||||
FROM fedora:31
|
||||
|
||||
RUN dnf -y install make cmake gcc gcc-c++ kernel-devel automake libtool bison pkgconf libacl-devel libasan librichacl-devel bzip2-devel zlib-devel xz-devel lz4-devel libzstd-devel openssl-devel groff ghostscript xz zip
|
||||
@@ -1,8 +0,0 @@
|
||||
FROM cirrusci/windowsservercore:2019
|
||||
|
||||
RUN choco install -y --no-progress --installargs 'ADD_CMAKE_TO_PATH=User' cmake
|
||||
RUN choco install -y --no-progress mingw
|
||||
RUN curl -o zlib-1.2.11.tar.gz https://www.zlib.net/zlib-1.2.11.tar.gz
|
||||
RUN tar -x -f zlib-1.2.11.tar.gz
|
||||
RUN cd zlib-1.2.11 && cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . && mingw32-make && mingw32-make install
|
||||
RUN del /f /q /s zlib-1.2.11 zlib-1.2.11.tar.gz
|
||||
@@ -1,9 +0,0 @@
|
||||
FROM cirrusci/windowsservercore:2019
|
||||
|
||||
RUN choco install -y --no-progress --installargs 'ADD_CMAKE_TO_PATH=User' cmake
|
||||
RUN choco install -y --no-progress visualstudio2017community
|
||||
RUN choco install -y --no-progress visualstudio2017-workload-vctools
|
||||
RUN curl -o zlib-1.2.11.tar.gz https://www.zlib.net/zlib-1.2.11.tar.gz
|
||||
RUN tar -x -f zlib-1.2.11.tar.gz
|
||||
RUN cd zlib-1.2.11 && cmake -G "Visual Studio 15 2017" . && cmake --build . --target ALL_BUILD --config Release && cmake --build . --target INSTALL --config Release
|
||||
RUN del /f /q /s zlib-1.2.11 zlib-1.2.11.tar.gz
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM cirrusci/windowsservercore:2019
|
||||
|
||||
RUN choco install -y --no-progress mingw
|
||||
RUN choco install -y --no-progress --installargs 'ADD_CMAKE_TO_PATH=User' cmake
|
||||
RUN choco install -y --no-progress visualstudio2017community
|
||||
RUN choco install -y --no-progress visualstudio2017-workload-vctools
|
||||
RUN curl -o zlib-1.2.11.tar.gz https://www.zlib.net/zlib-1.2.11.tar.gz
|
||||
RUN tar -x -f zlib-1.2.11.tar.gz
|
||||
RUN cd zlib-1.2.11 && cmake -G "Visual Studio 15 2017" . && cmake --build . --target ALL_BUILD --config Release && cmake --build . --target INSTALL --config Release
|
||||
RUN del /f /q /s zlib-1.2.11 zlib-1.2.11.tar.gz
|
||||
RUN choco install -y --no-progress cygwin
|
||||
RUN C:\tools\cygwin\cygwinsetup.exe -q -P make,autoconf,automake,cmake,gcc-core,binutils,libtool,pkg-config,bison,zlib-devel,libbz2-devel,liblzma-devel,liblz4-devel,libiconv-devel,libxml2-devel,libzstd-devel,libssl-devel
|
||||
@@ -1,122 +0,0 @@
|
||||
@ECHO OFF
|
||||
SET ZLIB_VERSION=1.2.11
|
||||
IF NOT "%BE%"=="cygwin-gcc" (
|
||||
IF NOT "%BE%"=="mingw-gcc" (
|
||||
IF NOT "%BE%"=="msvc" (
|
||||
ECHO Environment variable BE must be cygwin-gcc, mingw-gcc or msvc
|
||||
EXIT /b 1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
IF "%1%"=="prepare" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
@ECHO ON
|
||||
choco install -y --no-progress cygwin || EXIT /b 1
|
||||
C:\tools\cygwin\cygwinsetup.exe -q -P make,autoconf,automake,cmake,gcc-core,binutils,libtool,pkg-config,bison,zlib-devel,libbz2-devel,liblzma-devel,liblz4-devel,libiconv-devel,libxml2-devel,libzstd-devel,libssl-devel || EXIT /b 1
|
||||
@EXIT /b 0
|
||||
) ELSE IF "%BE%"=="mingw-gcc" (
|
||||
@ECHO ON
|
||||
choco install -y --no-progress mingw || EXIT /b 1
|
||||
choco install -y --no-progress --installargs 'ADD_CMAKE_TO_PATH=System' cmake || EXIT /b 1
|
||||
@EXIT /b 0
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
@ECHO ON
|
||||
choco install -y --no-progress visualstudio2017community || EXIT /b 1
|
||||
choco install -y --no-progress visualstudio2017-workload-vctools || EXIT /b 1
|
||||
choco install -y --no-progress --installargs 'ADD_CMAKE_TO_PATH=System' cmake || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1"=="deplibs" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
ECHO Skipping on this platform
|
||||
EXIT /b 0
|
||||
)
|
||||
IF NOT EXIST build_ci\libs (
|
||||
MKDIR build_ci\libs
|
||||
)
|
||||
CD build_ci\libs
|
||||
IF NOT EXIST zlib-%ZLIB_VERSION%.tar.gz (
|
||||
curl -o zlib-%ZLIB_VERSION%.tar.gz https://www.zlib.net/zlib-%ZLIB_VERSION%.tar.gz
|
||||
)
|
||||
IF NOT EXIST zlib-%ZLIB_VERSION% (
|
||||
tar -x -z -f zlib-%ZLIB_VERSION%.tar.gz
|
||||
)
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
CD zlib-%ZLIB_VERSION%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
mingw32-make || EXIT /b 1
|
||||
mingw32-make test || EXIT /b 1
|
||||
mingw32-make install || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
cmake -G "Visual Studio 15 2017" . || EXIT /b 1
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="configure" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET CONFIGURE_ARGS=-DENABLE_ACL=OFF
|
||||
C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a configure" || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
MKDIR build_ci\cmake
|
||||
CD build_ci\cmake
|
||||
cmake -G "MinGW Makefiles" ..\.. || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
MKDIR build_ci\cmake
|
||||
CD build_ci\cmake
|
||||
cmake -G "Visual Studio 15 2017" -D CMAKE_BUILD_TYPE="Release" ..\.. || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="build" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a build"
|
||||
) ELSE IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
CD build_ci\cmake
|
||||
mingw32-make || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
CD build_ci\cmake
|
||||
cmake --build . --target ALL_BUILD --config Release
|
||||
)
|
||||
) ELSE IF "%1%"=="test" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
ECHO "Skipping tests on this platform"
|
||||
EXIT /b 0
|
||||
REM SET BS=cmake
|
||||
REM SET SKIP_TEST_SPARSE=1
|
||||
REM C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a test"
|
||||
) ELSE IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
COPY "C:\Program Files (x86)\zlib\bin\libzlib.dll" build_ci\cmake\bin\
|
||||
CD build_ci\cmake
|
||||
SET SKIP_TEST_SPARSE=1
|
||||
mingw32-make test
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
ECHO "Skipping tests on this platform"
|
||||
EXIT /b 0
|
||||
REM CD build_ci\cmake
|
||||
REM cmake --build . --target RUN_TESTS --config Release
|
||||
)
|
||||
) ELSE IF "%1%"=="install" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
C:\tools\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a install"
|
||||
) ELSE IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
CD build_ci\cmake
|
||||
mingw32-make install DESTDIR=%cd%\destdir
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
SET PATH=%PATH%;C:\Program Files\cmake\bin;C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin
|
||||
cmake --build . --target INSTALL --config Release
|
||||
)
|
||||
) ELSE (
|
||||
ECHO "Usage: %0% prepare|deplibs|configure|build|test|install"
|
||||
@EXIT /b 0
|
||||
)
|
||||
@EXIT /b 0
|
||||
@@ -1,66 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ $# != 1 ]
|
||||
then
|
||||
echo "Usage: $0 prepare | test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
UNAME=`uname`
|
||||
if [ "$1" = "prepare" ]
|
||||
then
|
||||
if [ "${UNAME}" = "FreeBSD" ]
|
||||
then
|
||||
set -x -e
|
||||
env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
|
||||
sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
|
||||
pkg update
|
||||
mount -u -o acls /
|
||||
mkdir /tmp_acl_nfsv4
|
||||
MD=`mdconfig -a -t swap -s 128M`
|
||||
newfs /dev/$MD
|
||||
tunefs -N enable /dev/$MD
|
||||
mount /dev/$MD /tmp_acl_nfsv4
|
||||
chmod 1777 /tmp_acl_nfsv4
|
||||
pkg install -y autoconf automake cmake libiconv libtool pkgconf expat libxml2 liblz4 zstd
|
||||
elif [ "${UNAME}" = "Darwin" ]
|
||||
then
|
||||
set -x -e
|
||||
brew update > /dev/null
|
||||
for pkg in autoconf automake libtool pkg-config cmake xz lz4 zstd
|
||||
do
|
||||
brew list $pkg > /dev/null && brew upgrade $pkg || brew install $pkg
|
||||
done
|
||||
elif [ "${UNAME}" = "Linux" ]
|
||||
then
|
||||
if [ -f "/etc/debian_version" ]
|
||||
then
|
||||
apt-get -y update
|
||||
apt-get -y install build-essential locales automake libtool bison pkgconf libacl1-dev libbz2-dev zlib1g-dev liblzma-dev liblz4-dev libzstd-dev libssl-dev lrzip cmake
|
||||
elif [ -f "/etc/fedora-release" ]
|
||||
then
|
||||
dnf -y install make cmake gcc gcc-c++ kernel-devel automake libtool bison pkgconf libacl-devel librichacl-devel bzip2-devel zlib-devel xz-devel lz4-devel libzstd-devel openssl-devel
|
||||
fi
|
||||
fi
|
||||
elif [ "$1" = "test" ]
|
||||
then
|
||||
if [ "${UNAME}" = "FreeBSD" ]
|
||||
then
|
||||
set -e
|
||||
echo "Additional NFSv4 ACL tests"
|
||||
CURDIR=`pwd`
|
||||
if [ "${BS}" = "cmake" ]
|
||||
then
|
||||
BIN_SUBDIR="bin"
|
||||
else
|
||||
BIN_SUBDIR=.
|
||||
fi
|
||||
BUILDDIR="${CURDIR}/build_ci/${BS}"
|
||||
cd "$BUILDDIR"
|
||||
TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4
|
||||
fi
|
||||
else
|
||||
echo "Usage: $0 prepare | test"
|
||||
exit 1
|
||||
fi
|
||||
+35
-104
@@ -1,126 +1,32 @@
|
||||
@ECHO OFF
|
||||
SET ZLIB_VERSION=1.3
|
||||
SET BZIP2_VERSION=1ea1ac188ad4b9cb662e3f8314673c63df95a589
|
||||
SET XZ_VERSION=5.6.3
|
||||
IF NOT "%BE%"=="mingw-gcc" (
|
||||
IF NOT "%BE%"=="msvc" (
|
||||
ECHO Environment variable BE must be mingw-gcc or msvc
|
||||
IF NOT "%BE%"=="cygwin-gcc" (
|
||||
ECHO Environment variable BE must be cygwin-gcc, mingw-gcc or msvc
|
||||
EXIT /b 1
|
||||
)
|
||||
)
|
||||
|
||||
REM v1.5.6 has a bug with the CMake files & MSVC
|
||||
REM https://github.com/facebook/zstd/issues/3999
|
||||
REM Fall back to 1.5.5 for MSVC until fixed
|
||||
IF "%BE%"=="msvc" (
|
||||
SET ZSTD_VERSION=1.5.5
|
||||
) ELSE (
|
||||
SET ZSTD_VERSION=1.5.6
|
||||
)
|
||||
|
||||
SET ORIGPATH=%PATH%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\Program Files\cmake\bin;C:\ProgramData\mingw64\mingw64\bin
|
||||
SET MINGWPATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;D:\msys64\mingw64\bin;C:\Program Files\cmake\bin
|
||||
)
|
||||
|
||||
IF "%1"=="deplibs" (
|
||||
IF NOT EXIST build_ci\libs (
|
||||
MKDIR build_ci\libs
|
||||
)
|
||||
CD build_ci\libs
|
||||
IF NOT EXIST zlib-%ZLIB_VERSION%.zip (
|
||||
ECHO Downloading https://github.com/libarchive/zlib/archive/v%ZLIB_VERSION%.zip
|
||||
curl -L -o zlib-%ZLIB_VERSION%.zip https://github.com/libarchive/zlib/archive/v%ZLIB_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST zlib-%ZLIB_VERSION% (
|
||||
ECHO Unpacking zlib-%ZLIB_VERSION%.zip
|
||||
C:\windows\system32\tar.exe -x -f zlib-%ZLIB_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST bzip2-%BZIP2_VERSION%.zip (
|
||||
echo Downloading https://github.com/libarchive/bzip2/archive/%BZIP2_VERSION%.zip
|
||||
curl -L -o bzip2-%BZIP2_VERSION%.zip https://github.com/libarchive/bzip2/archive/%BZIP2_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST bzip2-%BZIP2_VERSION% (
|
||||
echo Unpacking bzip2-%BZIP2_VERSION%.zip
|
||||
C:\windows\system32\tar.exe -x -f bzip2-%BZIP2_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST xz-%XZ_VERSION%.zip (
|
||||
echo Downloading https://github.com/libarchive/xz/archive/%XZ_VERSION%.zip
|
||||
curl -L -o xz-%XZ_VERSION%.zip https://github.com/libarchive/xz/archive/v%XZ_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST xz-%XZ_VERSION% (
|
||||
echo Unpacking xz-%XZ_VERSION%.zip
|
||||
C:\windows\system32\tar.exe -x -f xz-%XZ_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST zstd-%ZSTD_VERSION%.zip (
|
||||
echo Downloading https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD_VERSION%.zip
|
||||
curl -L -o zstd-%ZSTD_VERSION%.zip https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
IF NOT EXIST zstd-%ZSTD_VERSION% (
|
||||
echo Unpacking zstd-%ZSTD_VERSION%.zip
|
||||
C:\windows\system32\tar.exe -x -f zstd-%ZSTD_VERSION%.zip || EXIT /b 1
|
||||
)
|
||||
CD zlib-%ZLIB_VERSION%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%MINGWPATH%
|
||||
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1
|
||||
mingw32-make test || EXIT /b 1
|
||||
mingw32-make install || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
cmake -G "Visual Studio 17 2022" . || EXIT /b 1
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
)
|
||||
CD ..
|
||||
CD bzip2-%BZIP2_VERSION%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%MINGWPATH%
|
||||
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
|
||||
mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1
|
||||
REM mingw32-make test || EXIT /b 1
|
||||
mingw32-make install || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ENABLE_LIB_ONLY=ON -D ENABLE_SHARED_LIB=OFF -D ENABLE_STATIC_LIB=ON . || EXIT /b 1
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
REM cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
)
|
||||
CD ..
|
||||
CD xz-%XZ_VERSION%
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%MINGWPATH%
|
||||
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1
|
||||
mingw32-make install || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
)
|
||||
CD ..
|
||||
CD zstd-%ZSTD_VERSION%\build\cmake
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%MINGWPATH%
|
||||
cmake -G "MinGW Makefiles" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
mingw32-make -j %NUMBER_OF_PROCESSORS% || EXIT /b 1
|
||||
mingw32-make install || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" . || EXIT /b 1
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="configure" (
|
||||
IF "%1%"=="configure" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
SET PATH=%MINGWPATH%
|
||||
MKDIR build_ci\cmake
|
||||
CD build_ci\cmake
|
||||
cmake -G "MinGW Makefiles" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/libzlibstatic.a" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/libbz2_static.a" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/liblzma.a" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" -D ZSTD_LIBRARY="C:/Program Files (x86)/zstd/lib/libzstd.a" -D ZSTD_INCLUDE_DIR="C:/Program Files (x86)/zstd/include" ..\.. || EXIT /b 1
|
||||
cmake -G "MinGW Makefiles" ..\.. || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
MKDIR build_ci\cmake
|
||||
CD build_ci\cmake
|
||||
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" -D ZLIB_LIBRARY="C:/Program Files (x86)/zlib/lib/zlibstatic.lib" -D ZLIB_INCLUDE_DIR="C:/Program Files (x86)/zlib/include" -D BZIP2_LIBRARIES="C:/Program Files (x86)/bzip2/lib/bz2_static.lib" -D BZIP2_INCLUDE_DIR="C:/Program Files (x86)/bzip2/include" -D LIBLZMA_LIBRARY="C:/Program Files (x86)/xz/lib/lzma.lib" -D LIBLZMA_INCLUDE_DIR="C:/Program Files (x86)/xz/include" -D ZSTD_LIBRARY="C:/Program Files (x86)/zstd/lib/zstd_static.lib" -D ZSTD_INCLUDE_DIR="C:/Program Files (x86)/zstd/include" ..\.. || EXIT /b 1
|
||||
cmake -G "Visual Studio 17 2022" -D CMAKE_BUILD_TYPE="Release" --toolchain "%VCPKG_INSTALLATION_ROOT%\scripts\buildsystems\vcpkg.cmake" -D VCPKG_TARGET_TRIPLET=x64-windows-static -D VCPKG_MANIFEST_DIR=%GITHUB_WORKSPACE%\build\ci\github_actions ..\.. || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET CYGWIN_NOWINPATH=1
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a configure" || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="build" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
@@ -130,6 +36,11 @@ IF "%1"=="deplibs" (
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
CD build_ci\cmake
|
||||
cmake --build . --target ALL_BUILD --config Release || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET MAKE_ARGS=-j
|
||||
SET CYGWIN_NOWINPATH=1
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a build" || EXIT /b 1
|
||||
)
|
||||
) ELSE IF "%1%"=="test" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
@@ -140,6 +51,13 @@ IF "%1"=="deplibs" (
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
CD build_ci\cmake
|
||||
cmake --build . --target RUN_TESTS --config Release || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="cygwin-gcc" (
|
||||
REM SET BS=cmake
|
||||
REM SET CYGWIN_NOWINPATH=1
|
||||
REM SET SKIP_TEST_SPARSE=1
|
||||
ECHO "Skipping tests on this platform"
|
||||
REM D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a test" || EXIT /b 1
|
||||
EXIT /b 0
|
||||
)
|
||||
) ELSE IF "%1%"=="install" (
|
||||
IF "%BE%"=="mingw-gcc" (
|
||||
@@ -149,9 +67,22 @@ IF "%1"=="deplibs" (
|
||||
) ELSE IF "%BE%"=="msvc" (
|
||||
CD build_ci\cmake
|
||||
cmake --build . --target INSTALL --config Release || EXIT /b 1
|
||||
) ELSE IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET CYGWIN_NOWINPATH=1
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a install" || EXIT /b 1
|
||||
REM Exit early here; the build.sh install step for Cygwin prints the version.
|
||||
EXIT /b 0
|
||||
)
|
||||
"C:\Program Files (x86)\libarchive\bin\bsdtar.exe" --version
|
||||
) ELSE IF "%1"=="artifact" (
|
||||
IF "%BE%"=="cygwin-gcc" (
|
||||
SET BS=cmake
|
||||
SET CYGWIN_NOWINPATH=1
|
||||
D:\cygwin\bin\bash.exe --login -c "cd '%cd%'; ./build/ci/build.sh -a artifact" || EXIT /b 1
|
||||
EXIT /b 0
|
||||
)
|
||||
|
||||
C:\windows\system32\tar.exe -c -C "C:\Program Files (x86)" --format=zip -f libarchive.zip libarchive
|
||||
) ELSE (
|
||||
ECHO "Usage: %0% deplibs|configure|build|test|install|artifact"
|
||||
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ $# != 1 ]
|
||||
then
|
||||
echo "Usage: $0 prepare | test"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "prepare" ]
|
||||
then
|
||||
set -x -e
|
||||
env ASSUME_ALWAYS_YES=yes pkg bootstrap -f
|
||||
sed -i.bak -e 's,pkg+http://pkg.FreeBSD.org/\${ABI}/quarterly,pkg+http://pkg.FreeBSD.org/\${ABI}/latest,' /etc/pkg/FreeBSD.conf
|
||||
pkg update
|
||||
mount -u -o acls /
|
||||
mkdir /tmp_acl_nfsv4
|
||||
MD=`mdconfig -a -t swap -s 128M`
|
||||
newfs /dev/$MD
|
||||
tunefs -N enable /dev/$MD
|
||||
mount /dev/$MD /tmp_acl_nfsv4
|
||||
chmod 1777 /tmp_acl_nfsv4
|
||||
pkg install -y autoconf automake cmake gmake libiconv libtool pkgconf expat libxml2 liblz4 zstd
|
||||
elif [ "$1" = "test" ]
|
||||
then
|
||||
set -e
|
||||
echo "Additional NFSv4 ACL tests"
|
||||
CURDIR=`pwd`
|
||||
if [ "${BS}" = "cmake" ]
|
||||
then
|
||||
BIN_SUBDIR="bin"
|
||||
else
|
||||
BIN_SUBDIR=.
|
||||
fi
|
||||
BUILDDIR="${CURDIR}/build_ci/${BS}"
|
||||
cd "$BUILDDIR"
|
||||
TMPDIR=/tmp_acl_nfsv4 ${BIN_SUBDIR}/libarchive_test -r "${CURDIR}/libarchive/test" -v test_acl_platform_nfs4
|
||||
else
|
||||
echo "Usage: $0 prepare | test"
|
||||
exit 1
|
||||
fi
|
||||
@@ -5,6 +5,9 @@ set -eux
|
||||
#brew update > /dev/null
|
||||
#brew upgrade > /dev/null
|
||||
|
||||
# Workaround for cmake in local/pinned tap issue
|
||||
brew uninstall cmake
|
||||
|
||||
# This does an upgrade if the package is already installed
|
||||
brew install \
|
||||
autoconf \
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"dependencies": [
|
||||
"zlib",
|
||||
"bzip2",
|
||||
"liblzma",
|
||||
"zstd"
|
||||
],
|
||||
"vcpkg-configuration": {
|
||||
"default-registry": {
|
||||
"kind": "git",
|
||||
"repository": "https://github.com/microsoft/vcpkg",
|
||||
"baseline": "44819aa2a6c10e56065e2b0330e7d6c89d1d2574"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,5 +29,5 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build/pkgconfig/libarchive.pc.in
|
||||
# And install it, of course ;).
|
||||
IF(ENABLE_INSTALL)
|
||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/build/pkgconfig/libarchive.pc
|
||||
DESTINATION "lib/pkgconfig")
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||
ENDIF()
|
||||
+21
-3
@@ -405,6 +405,12 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the `chroot' function. */
|
||||
#cmakedefine HAVE_CHROOT 1
|
||||
|
||||
/* Define to 1 if you have the `closefrom' function. */
|
||||
#cmakedefine HAVE_CLOSEFROM 1
|
||||
|
||||
/* Define to 1 if you have the `close_range' function. */
|
||||
#cmakedefine HAVE_CLOSE_RANGE 1
|
||||
|
||||
/* Define to 1 if you have the <copyfile.h> header file. */
|
||||
#cmakedefine HAVE_COPYFILE_H 1
|
||||
|
||||
@@ -636,6 +642,9 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the `getea' function. */
|
||||
#cmakedefine HAVE_GETEA 1
|
||||
|
||||
/* Define to 1 if you have the `getegid' function. */
|
||||
#cmakedefine HAVE_GETEGID 1
|
||||
|
||||
/* Define to 1 if you have the `geteuid' function. */
|
||||
#cmakedefine HAVE_GETEUID 1
|
||||
|
||||
@@ -657,6 +666,9 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the `getpwuid_r' function. */
|
||||
#cmakedefine HAVE_GETPWUID_R 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#cmakedefine HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `getvfsbyname' function. */
|
||||
#cmakedefine HAVE_GETVFSBYNAME 1
|
||||
|
||||
@@ -675,6 +687,9 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the <iconv.h> header file. */
|
||||
#cmakedefine HAVE_ICONV_H 1
|
||||
|
||||
/* Define to 1 if you have the <intsafe.h> header file. */
|
||||
#cmakedefine HAVE_INTSAFE_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#cmakedefine HAVE_INTTYPES_H 1
|
||||
|
||||
@@ -970,9 +985,6 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
#cmakedefine HAVE_PWD_H 1
|
||||
|
||||
/* Define to 1 if you have the `readdir_r' function. */
|
||||
#cmakedefine HAVE_READDIR_R 1
|
||||
|
||||
/* Define to 1 if you have the `readlink' function. */
|
||||
#cmakedefine HAVE_READLINK 1
|
||||
|
||||
@@ -1019,9 +1031,15 @@ typedef uint64_t uintmax_t;
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#cmakedefine HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdckdint.h> header file. */
|
||||
#cmakedefine HAVE_STDCKDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#cmakedefine HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#cmakedefine HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#cmakedefine HAVE_STDLIB_H 1
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Generated by CMake at configure time -- do not edit.
|
||||
# Scans test source files for DEFINE_TEST() declarations and writes list.h.
|
||||
set(_sources @SOURCES@)
|
||||
set(_output "@OUTPUT@")
|
||||
file(WRITE "${_output}" "")
|
||||
foreach(_src ${_sources})
|
||||
if(_src MATCHES "test_[^/]+\\.c$")
|
||||
file(STRINGS "${_src}" _lines REGEX "^DEFINE_TEST")
|
||||
foreach(_line ${_lines})
|
||||
file(APPEND "${_output}" "${_line}\n")
|
||||
endforeach()
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveAssignments:
|
||||
AlignFunctionDeclarations: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AlignOperands: DontAlign
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
BinPackParameters: OnePerLine
|
||||
BreakBeforeTemplateCloser: true
|
||||
BreakConstructorInitializers: AfterColon
|
||||
BreakInheritanceList: AfterComma
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 120
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
EnumTrailingComma: Insert
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentGotoLabels: false
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 8
|
||||
PPIndentWidth: 1
|
||||
PackConstructorInitializers: BinPack
|
||||
PointerAlignment: Right
|
||||
QualifierAlignment: Left
|
||||
RemoveEmptyLinesInUnwrappedLines: true
|
||||
SeparateDefinitionBlocks: Always
|
||||
SortIncludes:
|
||||
Enabled: false
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: false
|
||||
AfterForeachMacros: false
|
||||
AfterIfMacros: false
|
||||
SpacesInContainerLiterals: false
|
||||
UseTab: ForIndentation
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
project(libarchive-clang-tools)
|
||||
find_package(zstd REQUIRED)
|
||||
find_package(Clang REQUIRED)
|
||||
add_executable(la-lint)
|
||||
|
||||
target_sources(la-lint
|
||||
PRIVATE
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_include_directories(la-lint
|
||||
PRIVATE
|
||||
${CLANG_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(la-lint
|
||||
PRIVATE
|
||||
LLVM LLVMCore LLVMSupport
|
||||
libclang clang-cpp
|
||||
)
|
||||
|
||||
install(TARGETS la-lint RUNTIME DESTINATION bin)
|
||||
@@ -0,0 +1,190 @@
|
||||
/*-
|
||||
* Copyright (c) 2026 Dustin L. Howett
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <clang/Frontend/FrontendActions.h>
|
||||
#include <clang/Frontend/TextDiagnosticPrinter.h>
|
||||
#include <clang/Frontend/ChainedDiagnosticConsumer.h>
|
||||
#include <clang/Tooling/CommonOptionsParser.h>
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
#include <clang/ASTMatchers/ASTMatchFinder.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
|
||||
#include <print>
|
||||
|
||||
using namespace clang::tooling;
|
||||
using namespace clang::ast_matchers;
|
||||
using namespace llvm;
|
||||
|
||||
static llvm::cl::OptionCategory LaToolCategory("la-clang-tool options");
|
||||
static llvm::cl::opt<std::string> Prefix("prefix",
|
||||
llvm::cl::desc("Project path prefix"),
|
||||
llvm::cl::init(""),
|
||||
llvm::cl::cat(LaToolCategory));
|
||||
static bool IsGithubCiBuild{};
|
||||
|
||||
struct MemCmpNeedleHandler : public MatchFinder::MatchCallback {
|
||||
virtual void run(const MatchFinder::MatchResult &result) {
|
||||
auto needle = result.Nodes.getNodeAs<clang::StringLiteral>("needle");
|
||||
auto lenExpr = result.Nodes.getNodeAs<clang::IntegerLiteral>("length");
|
||||
|
||||
/*
|
||||
* This check uses [less than] rather than [less equal] because in some formats we want to verify the
|
||||
* presence of the null terminator and in others we do not.
|
||||
*/
|
||||
if(lenExpr->getValue().ult(needle->getLength())) {
|
||||
auto &diag = result.Context->getDiagnostics();
|
||||
auto did = diag.getCustomDiagID(clang::DiagnosticsEngine::Level::Error,
|
||||
"memcmp needle has length `%0', but is checked with length `%1'");
|
||||
clang::DiagnosticBuilder db = diag.Report(lenExpr->getLocation(), did);
|
||||
db.AddTaggedVal(needle->getLength(), clang::DiagnosticsEngine::ArgumentKind::ak_uint);
|
||||
db.AddTaggedVal(lenExpr->getValue().getSExtValue(),
|
||||
clang::DiagnosticsEngine::ArgumentKind::ak_sint);
|
||||
db.AddSourceRange(clang::CharSourceRange::getCharRange(needle->getSourceRange()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct AssertUAFHandler : public MatchFinder::MatchCallback {
|
||||
virtual void run(const MatchFinder::MatchResult &result) {
|
||||
/*
|
||||
* This code uses getFileLoc to specify locations disregarding macro expansion
|
||||
* and to avoid Clang printing "macro expanded from here".
|
||||
*/
|
||||
auto &SM = *result.SourceManager;
|
||||
auto uaf = result.Nodes.getNodeAs<clang::DeclRefExpr>("uaf");
|
||||
auto assertion = result.Nodes.getNodeAs<clang::CallExpr>("assertion");
|
||||
auto freed = result.Nodes.getNodeAs<clang::CallExpr>("free");
|
||||
|
||||
auto &diag = result.Context->getDiagnostics();
|
||||
{
|
||||
auto did = diag.getCustomDiagID(clang::DiagnosticsEngine::Level::Error,
|
||||
"test assertion uses `%0' after free; prefer assertEqualInt");
|
||||
clang::DiagnosticBuilder db = diag.Report(SM.getFileLoc(uaf->getBeginLoc()), did);
|
||||
db.AddString(uaf->getNameInfo().getAsString());
|
||||
db << clang::FixItHint::CreateReplacement(
|
||||
clang::SourceRange{SM.getFileLoc(assertion->getBeginLoc()),
|
||||
SM.getFileLoc(uaf->getBeginLoc())},
|
||||
"assertEqualInt(");
|
||||
}
|
||||
|
||||
{
|
||||
auto did = diag.getCustomDiagID(clang::DiagnosticsEngine::Level::Note, "`%0' freed here");
|
||||
clang::DiagnosticBuilder db = diag.Report(freed->getBeginLoc(), did);
|
||||
db.AddString(uaf->getNameInfo().getAsString());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class GithubActionDiagnosticConsumer : public clang::DiagnosticConsumer {
|
||||
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) {
|
||||
static constexpr const char *levels[] = {nullptr, "notice", "notice", "warning", "error", "error"};
|
||||
|
||||
const auto level = levels[DiagLevel];
|
||||
if(!level)
|
||||
return;
|
||||
|
||||
auto &SM = Info.getSourceManager();
|
||||
auto loc = Info.getLocation();
|
||||
loc = SM.getFileLoc(loc);
|
||||
|
||||
auto file = SM.getFilename(loc);
|
||||
if(file.empty()) {
|
||||
return;
|
||||
}
|
||||
file.consume_front_insensitive(Prefix);
|
||||
while(file.consume_front("/")) {}
|
||||
|
||||
bool lineInvalid = false;
|
||||
auto line = SM.getLineNumber(loc, &lineInvalid);
|
||||
if(lineInvalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
llvm::SmallVector<char> diagString;
|
||||
Info.FormatDiagnostic(diagString);
|
||||
|
||||
std::print("::{0} file={1},line={2},title=Lint::{3}\n", level, std::string_view{file}, line,
|
||||
std::string_view{diagString});
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
auto exp = CommonOptionsParser::create(argc, argv, LaToolCategory);
|
||||
auto &optionsParser = exp.get();
|
||||
ClangTool tool(optionsParser.getCompilations(), optionsParser.getSourcePathList());
|
||||
|
||||
if(const char *e = getenv("GITHUB_WORKSPACE")) {
|
||||
IsGithubCiBuild = true;
|
||||
|
||||
if(Prefix.c_str()[0] == '\0') {
|
||||
Prefix.assign(e);
|
||||
Prefix.append("/");
|
||||
}
|
||||
}
|
||||
|
||||
MatchFinder finder;
|
||||
|
||||
/*
|
||||
* Find every assertion_equal_mem that passes a string literal.
|
||||
* --> assertEqualMem(foo, "literal", 7);
|
||||
*/
|
||||
MemCmpNeedleHandler memCmpHandler;
|
||||
finder.addMatcher(callExpr(callee(functionDecl(hasName("assertion_equal_mem"))),
|
||||
hasArgument(4, stringLiteral().bind("needle")),
|
||||
hasArgument(6, integerLiteral(anything()).bind("length"))),
|
||||
&memCmpHandler);
|
||||
|
||||
/*
|
||||
* Find every assertion_equal_int whose call site contains a `free` function,
|
||||
* and then passes the freed decl to assertion_equal_int as context.
|
||||
* --> assertEqualIntA(a, ARCHIVE_OK, archive_write_free(a));
|
||||
* ^-- must be the same as ----------^
|
||||
*/
|
||||
AssertUAFHandler uafHandler;
|
||||
finder.addMatcher(
|
||||
callExpr(callee(functionDecl(hasName("assertion_equal_int"))),
|
||||
hasArgument(4,
|
||||
callExpr(callee(functionDecl(matchesName("archive.*_free$"))),
|
||||
hasArgument(0, declRefExpr(to(varDecl(anything()).bind("freed")))))
|
||||
.bind("free")),
|
||||
hasArgument(6, declRefExpr(to(varDecl(declaresSameEntityAsBoundNode("freed")))).bind("uaf")))
|
||||
.bind("assertion"),
|
||||
&uafHandler);
|
||||
|
||||
std::unique_ptr<clang::DiagnosticConsumer> diagnosticConsumer;
|
||||
|
||||
if(IsGithubCiBuild) {
|
||||
/* Emit GitHub-formatted error messages by default when we are building in GitHub Actions */
|
||||
clang::DiagnosticOptions diagOptions;
|
||||
diagOptions.ShowColors = true;
|
||||
clang::TextDiagnosticPrinter defaultDiag(llvm::errs(), diagOptions, false);
|
||||
diagnosticConsumer = std::make_unique<clang::ChainedDiagnosticConsumer>(&defaultDiag,
|
||||
std::make_unique<GithubActionDiagnosticConsumer>());
|
||||
tool.setDiagnosticConsumer(diagnosticConsumer.get());
|
||||
}
|
||||
|
||||
return tool.run(newFrontendActionFactory(&finder).get());
|
||||
}
|
||||
@@ -50,8 +50,8 @@ export MAKE_LIBARCHIVE_RELEASE="1"
|
||||
/bin/sh build/autogen.sh
|
||||
|
||||
# Get the newest config.guess/config.sub from savannah.gnu.org
|
||||
curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > build/autoconf/config.guess
|
||||
curl 'http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' > build/autoconf/config.sub
|
||||
curl -fsSL 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD' > build/autoconf/config.guess
|
||||
curl -fsSL 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD' > build/autoconf/config.sub
|
||||
|
||||
./configure
|
||||
make distcheck
|
||||
|
||||
@@ -3,8 +3,8 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
RUN ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
|
||||
RUN apt-get update && apt-get install -y build-essential autoconf automake libtool pkg-config cmake zlib1g-dev libssl-dev libacl1-dev libbz2-dev liblzma-dev liblz4-dev libzstd-dev lzop groff ghostscript bsdmainutils zip
|
||||
ADD . $HOME/libarchive/
|
||||
ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" $HOME/libarchive/build/autoconf/config.guess
|
||||
ADD "http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" $HOME/libarchive/build/autoconf/config.sub
|
||||
ADD "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" $HOME/libarchive/build/autoconf/config.guess
|
||||
ADD "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" $HOME/libarchive/build/autoconf/config.sub
|
||||
WORKDIR $HOME/libarchive
|
||||
RUN /bin/sh build/clean.sh
|
||||
RUN /bin/sh build/autogen.sh
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3008000
|
||||
3008009
|
||||
+2
-2
@@ -13,8 +13,8 @@ IF(ENABLE_CAT)
|
||||
bsdcat.h
|
||||
bsdcat_platform.h
|
||||
cmdline.c
|
||||
../libarchive_fe/err.c
|
||||
../libarchive_fe/err.h
|
||||
../libarchive_fe/lafe_err.c
|
||||
../libarchive_fe/lafe_err.h
|
||||
../libarchive_fe/lafe_platform.h
|
||||
)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libarchive_fe)
|
||||
|
||||
+14
-1
@@ -7,6 +7,9 @@
|
||||
|
||||
#include "bsdcat_platform.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
@@ -22,7 +25,7 @@
|
||||
#include <archive_entry.h>
|
||||
|
||||
#include "bsdcat.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
#define BYTES_PER_BLOCK (20*512)
|
||||
|
||||
@@ -105,6 +108,16 @@ main(int argc, char **argv)
|
||||
bsdcat = &bsdcat_storage;
|
||||
memset(bsdcat, 0, sizeof(*bsdcat));
|
||||
|
||||
#if defined(HAVE_SIGACTION) && defined(SIGCHLD)
|
||||
{ /* Do not ignore SIGCHLD. */
|
||||
struct sigaction sa;
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
lafe_setprogname(*argv, "bsdcat");
|
||||
|
||||
bsdcat->argv = argv;
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
#endif
|
||||
|
||||
#include "bsdcat.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for bsdcat. Please keep this sorted.
|
||||
|
||||
+3
-16
@@ -3,7 +3,7 @@
|
||||
#
|
||||
############################################
|
||||
#
|
||||
# How to build bsdtar_test
|
||||
# How to build bsdcat_test
|
||||
#
|
||||
############################################
|
||||
IF(ENABLE_CAT AND ENABLE_TEST)
|
||||
@@ -51,25 +51,12 @@ IF(ENABLE_CAT AND ENABLE_TEST)
|
||||
# Generate list.h by grepping DEFINE_TEST() lines out of the C sources.
|
||||
#
|
||||
GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
|
||||
${CMAKE_CURRENT_LIST_FILE} ${bsdcat_test_SOURCES})
|
||||
${CMAKE_CURRENT_LIST_FILE} bsdcat_test ${bsdcat_test_SOURCES})
|
||||
SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# list.h has a line DEFINE_TEST(testname) for every
|
||||
# test. We can use that to define the tests for cmake by
|
||||
# defining a DEFINE_TEST macro and reading list.h in.
|
||||
MACRO (DEFINE_TEST _testname)
|
||||
ADD_TEST(
|
||||
NAME bsdcat_${_testname}
|
||||
COMMAND bsdcat_test -vv
|
||||
-p $<TARGET_FILE:bsdcat>
|
||||
-r ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-s
|
||||
${_testname})
|
||||
SET_TESTS_PROPERTIES(bsdcat_${_testname} PROPERTIES SKIP_RETURN_CODE 2)
|
||||
ENDMACRO (DEFINE_TEST _testname)
|
||||
DISCOVER_TESTS(bsdcat ${bsdcat_test_SOURCES})
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cat/test)
|
||||
|
||||
+34
-30
@@ -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.0dev])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3008000])
|
||||
m4_define([LIBARCHIVE_VERSION_S],[3.8.9])
|
||||
m4_define([LIBARCHIVE_VERSION_N],[3008009])
|
||||
|
||||
dnl bsdtar and bsdcpio versioning tracks libarchive
|
||||
m4_define([BSDTAR_VERSION_S],LIBARCHIVE_VERSION_S())
|
||||
@@ -101,6 +101,9 @@ esac
|
||||
AM_CONDITIONAL([INC_WINDOWS_FILES], [test $inc_windows_files = yes])
|
||||
AM_CONDITIONAL([INC_CYGWIN_FILES], [test $inc_cygwin_files = yes])
|
||||
|
||||
dnl On native Windows (MinGW), embedding the manifest needs windres
|
||||
AS_IF([test $inc_windows_files = yes], [AC_CHECK_TOOL([WINDRES], [windres])])
|
||||
|
||||
dnl Defines that are required for specific platforms (e.g. -D_POSIX_SOURCE, etc)
|
||||
PLATFORMCPPFLAGS=
|
||||
case "$host_os" in
|
||||
@@ -258,7 +261,8 @@ AM_CONDITIONAL([STATIC_BSDCPIO], [ test "$static_bsdcpio" = yes ])
|
||||
case $host in
|
||||
*mingw* | *cygwin* | *msys* )
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#ifdef _WIN32_WINNT
|
||||
[[#include <windows.h>
|
||||
#ifdef _WIN32_WINNT
|
||||
# error _WIN32_WINNT already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
@@ -267,7 +271,8 @@ case $host in
|
||||
AC_DEFINE([NTDDI_VERSION], 0x05020000, [Define to '0x05020000' for Windows Server 2003 APIs.])
|
||||
])
|
||||
AC_PREPROC_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#ifdef WINVER
|
||||
[[#include <windows.h>
|
||||
#ifdef WINVER
|
||||
# error WINVER already defined
|
||||
#endif
|
||||
]],[[;]])
|
||||
@@ -363,9 +368,9 @@ AS_VAR_IF([ac_cv_have_decl_FS_IOC_GETFLAGS], [yes],
|
||||
[AC_DEFINE_UNQUOTED([HAVE_WORKING_FS_IOC_GETFLAGS], [1],
|
||||
[Define to 1 if you have a working FS_IOC_GETFLAGS])])
|
||||
|
||||
AC_CHECK_HEADERS([locale.h membership.h paths.h poll.h pthread.h pwd.h])
|
||||
AC_CHECK_HEADERS([readpassphrase.h signal.h spawn.h])
|
||||
AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
|
||||
AC_CHECK_HEADERS([intsafe.h locale.h membership.h paths.h poll.h pthread.h])
|
||||
AC_CHECK_HEADERS([pwd.h readpassphrase.h signal.h spawn.h])
|
||||
AC_CHECK_HEADERS([stdarg.h stdckdint.h stdint.h stdlib.h string.h])
|
||||
AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/ea.h sys/extattr.h])
|
||||
AC_CHECK_HEADERS([sys/ioctl.h sys/mkdev.h sys/mount.h])
|
||||
AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/richacl.h])
|
||||
@@ -375,7 +380,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
|
||||
@@ -436,13 +441,15 @@ if test "x$with_bz2lib" != "xno"; then
|
||||
esac
|
||||
fi
|
||||
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
AC_ARG_WITH([libb2],
|
||||
AS_HELP_STRING([--without-libb2], [Don't build support for BLAKE2 through libb2]))
|
||||
|
||||
if test "x$with_libb2" != "xno"; then
|
||||
AC_CHECK_HEADERS([blake2.h])
|
||||
AC_CHECK_LIB(b2,blake2sp_init)
|
||||
BLAKE2_PC_VER=`pkg-config --modversion libb2`
|
||||
BLAKE2_PC_VER=`$PKG_CONFIG --modversion libb2`
|
||||
if test "x$BLAKE2_PC_VER" != "x"; then
|
||||
AC_DEFINE_UNQUOTED([LIBB2_PKGCONFIG_VERSION], ["$BLAKE2_PC_VER"], [Libb2 version coming from pkg-config.])
|
||||
fi
|
||||
@@ -817,16 +824,20 @@ AC_FUNC_VPRINTF
|
||||
# To avoid necessity for including windows.h or special forward declaration
|
||||
# workarounds, we use 'void *' for 'struct SECURITY_ATTRIBUTES *'
|
||||
AC_CHECK_STDCALL_FUNC([CreateHardLinkA],[const char *, const char *, void *])
|
||||
AC_CHECK_FUNCS([arc4random_buf chflags chown chroot ctime_r])
|
||||
AC_CHECK_FUNCS([arc4random_buf chflags chown chroot])
|
||||
AC_CHECK_FUNCS([closefrom close_range ctime_r])
|
||||
AC_CHECK_FUNCS([fchdir fchflags fchmod fchown fcntl fdopendir fnmatch fork])
|
||||
AC_CHECK_FUNCS([fstat fstatat fstatfs fstatvfs ftruncate])
|
||||
AC_CHECK_FUNCS([futimens futimes futimesat])
|
||||
AC_CHECK_FUNCS([geteuid getline getpid getgrgid_r getgrnam_r])
|
||||
AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r])
|
||||
AC_CHECK_FUNCS([getegid geteuid getline getpid getresgid getresuid])
|
||||
AC_CHECK_FUNCS([getgrgid_r getgrnam_r getpwnam_r getpwuid_r])
|
||||
AC_CHECK_FUNCS([gettimeofday getvfsbyname gmtime_r])
|
||||
AC_CHECK_FUNCS([issetugid])
|
||||
AC_CHECK_FUNCS([lchflags lchmod lchown link linkat localtime_r lstat lutimes])
|
||||
AC_CHECK_FUNCS([mbrtowc memmove memset])
|
||||
AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp])
|
||||
AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat])
|
||||
AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawn posix_spawnp])
|
||||
AC_CHECK_FUNCS([readlink readlinkat])
|
||||
AC_CHECK_FUNCS([readpassphrase])
|
||||
AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
|
||||
AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strnlen strrchr symlink])
|
||||
@@ -877,14 +888,6 @@ AC_CHECK_TYPES(struct statfs,,,
|
||||
#include <sys/mount.h>
|
||||
])
|
||||
|
||||
# There are several variants of readdir_r around; we only
|
||||
# accept the POSIX-compliant version.
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <dirent.h>]],
|
||||
[[DIR *dir; struct dirent e, *r;
|
||||
return(readdir_r(dir, &e, &r));]])],
|
||||
[AC_DEFINE(HAVE_READDIR_R,1,[Define to 1 if you have a POSIX compatible readdir_r])]
|
||||
)
|
||||
# dirfd can be either a function or a macro.
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <dirent.h>
|
||||
@@ -925,7 +928,7 @@ if test "x$enable_xattr" != "xno"; then
|
||||
])
|
||||
AC_CHECK_DECLS([XATTR_NOFOLLOW], [], [], [#include <sys/xattr.h>
|
||||
])
|
||||
ATTR_PC_VER=`pkg-config --modversion libattr`
|
||||
ATTR_PC_VER=`$PKG_CONFIG --modversion libattr`
|
||||
if test "x$ATTR_PC_VER" != "x"; then
|
||||
AC_DEFINE_UNQUOTED([LIBATTR_PKGCONFIG_VERSION], ["$ATTR_PC_VER"], [Libattr version coming from pkg-config.])
|
||||
fi
|
||||
@@ -1024,7 +1027,7 @@ AC_ARG_ENABLE([acl],
|
||||
if test "x$enable_acl" != "xno"; then
|
||||
# Libacl
|
||||
AC_CHECK_LIB([acl], [acl_get_file])
|
||||
ACL_PC_VER=`pkg-config --modversion libacl`
|
||||
ACL_PC_VER=`$PKG_CONFIG --modversion libacl`
|
||||
if test "x$ACL_PC_VER" != "x"; then
|
||||
AC_DEFINE_UNQUOTED([LIBACL_PKGCONFIG_VERSION], ["$ACL_PC_VER"], [Libacl version coming from pkg-config.])
|
||||
fi
|
||||
@@ -1038,7 +1041,7 @@ if test "x$enable_acl" != "xno"; then
|
||||
])
|
||||
|
||||
AC_CHECK_LIB([richacl], [richacl_get_file])
|
||||
RICHACL_PC_VER=`pkg-config --modversion librichacl`
|
||||
RICHACL_PC_VER=`$PKG_CONFIG --modversion librichacl`
|
||||
if test "x$RICHACL_PC_VER" != "x"; then
|
||||
AC_DEFINE_UNQUOTED([LIBRICHACL_PKGCONFIG_VERSION], ["$RICHACL_PC_VER"], [Librichacl version coming from pkg-config.])
|
||||
fi
|
||||
@@ -1291,24 +1294,26 @@ main(int argc, char **argv)
|
||||
case "$host_os" in
|
||||
*mingw* | *cygwin* | *msys*)
|
||||
;;
|
||||
*darwin*)
|
||||
CRYPTO_CHECK(MD5, LIBSYSTEM, md5)
|
||||
CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1)
|
||||
CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256)
|
||||
CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384)
|
||||
CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512)
|
||||
;;
|
||||
*)
|
||||
CRYPTO_CHECK(MD5, LIBC, md5)
|
||||
CRYPTO_CHECK(MD5, LIBSYSTEM, md5)
|
||||
CRYPTO_CHECK(RMD160, LIBC, rmd160)
|
||||
CRYPTO_CHECK(SHA1, LIBC, sha1)
|
||||
CRYPTO_CHECK(SHA1, LIBSYSTEM, sha1)
|
||||
CRYPTO_CHECK(SHA256, LIBC, sha256)
|
||||
CRYPTO_CHECK(SHA256, LIBC2, sha256)
|
||||
CRYPTO_CHECK(SHA256, LIBC3, sha256)
|
||||
CRYPTO_CHECK(SHA256, LIBSYSTEM, sha256)
|
||||
CRYPTO_CHECK(SHA384, LIBC, sha384)
|
||||
CRYPTO_CHECK(SHA384, LIBC2, sha384)
|
||||
CRYPTO_CHECK(SHA384, LIBC3, sha384)
|
||||
CRYPTO_CHECK(SHA384, LIBSYSTEM, sha384)
|
||||
CRYPTO_CHECK(SHA512, LIBC, sha512)
|
||||
CRYPTO_CHECK(SHA512, LIBC2, sha512)
|
||||
CRYPTO_CHECK(SHA512, LIBC3, sha512)
|
||||
CRYPTO_CHECK(SHA512, LIBSYSTEM, sha512)
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -1373,7 +1378,6 @@ AC_SUBST(LIBSREQUIRED)
|
||||
|
||||
# Probe libmd AFTER OpenSSL/libcrypto.
|
||||
# The two are incompatible and OpenSSL is more complete.
|
||||
AC_CHECK_HEADERS([md5.h ripemd.h sha.h sha256.h sha512.h])
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(md, MD5Init)
|
||||
CRYPTO_CHECK(MD5, LIBMD, md5)
|
||||
|
||||
@@ -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 \
|
||||
@@ -151,7 +158,9 @@ else
|
||||
libarchive_host_src_files :=
|
||||
endif
|
||||
|
||||
libarchive_fe_src_files := libarchive_fe/err.c \
|
||||
libarchive_fe_src_files := libarchive_fe/lafe_err.c \
|
||||
libarchive_fe/lafe_fnmatch.c \
|
||||
libarchive_fe/lafe_getline.c \
|
||||
libarchive_fe/line_reader.c \
|
||||
libarchive_fe/passphrase.c
|
||||
|
||||
@@ -305,4 +314,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,6 +42,8 @@
|
||||
|
||||
#define HAVE_CHOWN 1
|
||||
#define HAVE_CHROOT 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
|
||||
@@ -53,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
|
||||
@@ -135,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
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#define HAVE_CHOWN 1
|
||||
#define HAVE_CHROOT 1
|
||||
#define HAVE_CLOSEFROM 1
|
||||
#define HAVE_CLOSE_RANGE 1
|
||||
#define HAVE_CTIME_R 1
|
||||
#define HAVE_CTYPE_H 1
|
||||
#define HAVE_DECL_EXTATTR_NAMESPACE_USER 0
|
||||
|
||||
@@ -175,6 +175,12 @@
|
||||
/* Define to 1 if you have the `chroot' function. */
|
||||
/* #undef HAVE_CHROOT */
|
||||
|
||||
/* Define to 1 if you have the `closefrom' function. */
|
||||
/* #undef HAVE_CLOSEFROM */
|
||||
|
||||
/* Define to 1 if you have the `close_range' function. */
|
||||
/* #undef HAVE_CLOSE_RANGE */
|
||||
|
||||
/* Define to 1 if you have the <copyfile.h> header file. */
|
||||
/* #undef HAVE_COPYFILE_H */
|
||||
|
||||
@@ -620,9 +626,6 @@
|
||||
/* Define to 1 if you have the <pwd.h> header file. */
|
||||
/* #undef HAVE_PWD_H */
|
||||
|
||||
/* Define to 1 if you have a POSIX compatible readdir_r */
|
||||
#define HAVE_READDIR_R 1
|
||||
|
||||
/* Define to 1 if you have the `readlink' function. */
|
||||
/* #undef HAVE_READLINK */
|
||||
|
||||
@@ -896,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
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <sys/vfs.h>
|
||||
|
||||
//dirent.h
|
||||
#define readdir_r readdir64_r
|
||||
#define readdir readdir64
|
||||
#define dirent dirent64
|
||||
//fcntl.h
|
||||
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 "
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
@@ -0,0 +1,9 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 30
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 30
|
||||
|
||||
[afl]
|
||||
timeout = 30
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 1048576
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
// Update entries[i] to reflect ownership changes from linkify.
|
||||
// If linkify cached the entry internally, entry is now NULL and the
|
||||
// resolver owns the object. If linkify swapped it with a previously
|
||||
// cached entry, entry points to that other object.
|
||||
entries[i] = entry;
|
||||
|
||||
// Free any entry returned via spare (complete hardlink pair)
|
||||
if (spare != NULL) {
|
||||
archive_entry_free(spare);
|
||||
}
|
||||
}
|
||||
|
||||
// Free remaining entries from the resolver (drain loop)
|
||||
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 that were NOT consumed by the resolver
|
||||
for (int i = 0; i < num_entries; i++) {
|
||||
if (entries[i] != NULL) {
|
||||
archive_entry_free(entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
archive_entry_linkresolver_free(resolver);
|
||||
return 0;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 65536
|
||||
timeout = 30
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 262144
|
||||
timeout = 30
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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="
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* 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 <stdio.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};
|
||||
static char g_start_dir[512] = {0};
|
||||
static char g_extract_dir[512] = {0};
|
||||
static char g_outside_dir[512] = {0};
|
||||
static char g_sentinel_path[512] = {0};
|
||||
|
||||
static int write_file(const char* path, const char* data) {
|
||||
FILE* f = fopen(path, "wb");
|
||||
size_t len = strlen(data);
|
||||
size_t written;
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
written = fwrite(data, 1, len, f);
|
||||
if (fclose(f) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return written == len ? 0 : -1;
|
||||
}
|
||||
|
||||
static int sentinel_is_unchanged() {
|
||||
char buf[32];
|
||||
FILE* f = fopen(g_sentinel_path, "rb");
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
size_t n = fread(buf, 1, sizeof(buf) - 1, f);
|
||||
fclose(f);
|
||||
buf[n] = '\0';
|
||||
return strcmp(buf, "outside-original") == 0;
|
||||
}
|
||||
|
||||
static int reset_temp_tree() {
|
||||
if (g_start_dir[0] != '\0') {
|
||||
if (chdir(g_start_dir) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
remove_directory_tree(g_temp_dir);
|
||||
if (mkdir(g_temp_dir, 0700) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(g_extract_dir, sizeof(g_extract_dir), "%s/extract", g_temp_dir);
|
||||
snprintf(g_outside_dir, sizeof(g_outside_dir), "%s/outside", g_temp_dir);
|
||||
snprintf(g_sentinel_path, sizeof(g_sentinel_path), "%s/outside/sentinel",
|
||||
g_temp_dir);
|
||||
|
||||
if (mkdir(g_extract_dir, 0700) != 0 || mkdir(g_outside_dir, 0700) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char existing[512];
|
||||
char existing_dir[512];
|
||||
char nested_existing[512];
|
||||
snprintf(existing, sizeof(existing), "%s/extract/existing", g_temp_dir);
|
||||
snprintf(existing_dir, sizeof(existing_dir), "%s/extract/dir", g_temp_dir);
|
||||
snprintf(nested_existing, sizeof(nested_existing),
|
||||
"%s/extract/dir/existing", g_temp_dir);
|
||||
if (mkdir(existing_dir, 0700) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return write_file(g_sentinel_path, "outside-original") ||
|
||||
write_file(existing, "inside") ||
|
||||
write_file(nested_existing, "inside");
|
||||
}
|
||||
|
||||
static void consume_path(DataConsumer* consumer, char* out, size_t out_size) {
|
||||
static const char* const kPaths[] = {
|
||||
"file",
|
||||
"dir/file",
|
||||
"dir/./file",
|
||||
"dir//file",
|
||||
"link",
|
||||
"link/file",
|
||||
"link/./file",
|
||||
"link//file",
|
||||
"../outside/sentinel",
|
||||
"../outside/new-file",
|
||||
"./../outside/sentinel",
|
||||
"dir/../file",
|
||||
"hardlink",
|
||||
"hardlink-with-data",
|
||||
"symlink",
|
||||
"existing",
|
||||
"dir/existing",
|
||||
};
|
||||
uint8_t selector = consumer->consume_byte();
|
||||
if ((selector & 0x80) != 0) {
|
||||
snprintf(out, out_size, "%s/extract/absolute-%u", g_temp_dir, selector);
|
||||
} else if ((selector & 0x40) != 0) {
|
||||
snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir);
|
||||
} else {
|
||||
snprintf(out, out_size, "%s",
|
||||
kPaths[selector % (sizeof(kPaths) / sizeof(kPaths[0]))]);
|
||||
}
|
||||
}
|
||||
|
||||
static void consume_linkname(DataConsumer* consumer, char* out,
|
||||
size_t out_size) {
|
||||
static const char* const kTargets[] = {
|
||||
"existing",
|
||||
"dir/existing",
|
||||
"link/sentinel",
|
||||
"link/./sentinel",
|
||||
"link//sentinel",
|
||||
"../outside/sentinel",
|
||||
"./../outside/sentinel",
|
||||
"dir/../existing",
|
||||
"missing-target",
|
||||
};
|
||||
uint8_t selector = consumer->consume_byte();
|
||||
if ((selector & 0x80) != 0) {
|
||||
snprintf(out, out_size, "%s/outside/sentinel", g_temp_dir);
|
||||
} else if ((selector & 0x40) != 0) {
|
||||
snprintf(out, out_size, "%s/extract/existing", g_temp_dir);
|
||||
} else {
|
||||
snprintf(out, out_size, "%s",
|
||||
kTargets[selector % (sizeof(kTargets) / sizeof(kTargets[0]))]);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
if (getcwd(g_start_dir, sizeof(g_start_dir)) == NULL) {
|
||||
g_start_dir[0] = '\0';
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (reset_temp_tree() != 0 || chdir(g_extract_dir) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DataConsumer consumer(buf, len);
|
||||
|
||||
struct archive *disk = archive_write_disk_new();
|
||||
if (disk == NULL) {
|
||||
if (g_start_dir[0] != '\0') {
|
||||
if (chdir(g_start_dir) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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_UNLINK;
|
||||
if (opt_flags & 0x80) flags |= ARCHIVE_EXTRACT_SAFE_WRITES;
|
||||
|
||||
flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS |
|
||||
ARCHIVE_EXTRACT_SECURE_NODOTDOT |
|
||||
ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS;
|
||||
|
||||
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;
|
||||
|
||||
char pathname[512];
|
||||
char linkname[512];
|
||||
consume_path(&consumer, pathname, sizeof(pathname));
|
||||
archive_entry_set_pathname(entry, pathname);
|
||||
|
||||
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);
|
||||
|
||||
if (S_ISLNK(mode)) {
|
||||
consume_linkname(&consumer, linkname, sizeof(linkname));
|
||||
archive_entry_set_symlink(entry, linkname);
|
||||
archive_entry_set_size(entry, 0);
|
||||
} else if (ftype == 3) {
|
||||
consume_linkname(&consumer, linkname, sizeof(linkname));
|
||||
archive_entry_set_hardlink(entry, linkname);
|
||||
}
|
||||
|
||||
archive_entry_set_uid(entry, 1000);
|
||||
archive_entry_set_gid(entry, 1000);
|
||||
archive_entry_set_mtime(entry, consumer.consume_i64(), 0);
|
||||
|
||||
uint8_t data_buf[256];
|
||||
size_t data_len = 0;
|
||||
if (S_ISREG(mode)) {
|
||||
data_len = consumer.consume_bytes(data_buf, 256);
|
||||
archive_entry_set_size(entry, data_len);
|
||||
}
|
||||
|
||||
// Write the entry header
|
||||
if (archive_write_header(disk, entry) == ARCHIVE_OK) {
|
||||
if (S_ISREG(mode) && 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);
|
||||
|
||||
if (!sentinel_is_unchanged()) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (g_start_dir[0] != '\0') {
|
||||
if (chdir(g_start_dir) != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
[libfuzzer]
|
||||
max_len = 65536
|
||||
timeout = 30
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -0,0 +1,10 @@
|
||||
[libfuzzer]
|
||||
max_len = 524288
|
||||
timeout = 60
|
||||
rss_limit_mb = 2048
|
||||
|
||||
[honggfuzz]
|
||||
timeout = 60
|
||||
|
||||
[afl]
|
||||
timeout = 60
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
# 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 \
|
||||
$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
|
||||
"$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."
|
||||
+2
-2
@@ -60,11 +60,11 @@ parseoct(const char *p, size_t n)
|
||||
{
|
||||
unsigned long i = 0;
|
||||
|
||||
while ((*p < '0' || *p > '7') && n > 0) {
|
||||
while (n > 0 && (*p < '0' || *p > '7')) {
|
||||
++p;
|
||||
--n;
|
||||
}
|
||||
while (*p >= '0' && *p <= '7' && n > 0) {
|
||||
while (n > 0 && *p >= '0' && *p <= '7') {
|
||||
i *= 8;
|
||||
i += *p - '0';
|
||||
++p;
|
||||
|
||||
+4
-2
@@ -13,8 +13,10 @@ IF(ENABLE_CPIO)
|
||||
cpio.c
|
||||
cpio.h
|
||||
cpio_platform.h
|
||||
../libarchive_fe/err.c
|
||||
../libarchive_fe/err.h
|
||||
../libarchive_fe/lafe_err.c
|
||||
../libarchive_fe/lafe_err.h
|
||||
../libarchive_fe/lafe_getline.c
|
||||
../libarchive_fe/lafe_getline.h
|
||||
../libarchive_fe/lafe_platform.h
|
||||
../libarchive_fe/line_reader.c
|
||||
../libarchive_fe/line_reader.h
|
||||
|
||||
+12
-5
@@ -11,6 +11,9 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_GRP_H
|
||||
#include <grp.h>
|
||||
#endif
|
||||
@@ -26,7 +29,7 @@
|
||||
#endif
|
||||
|
||||
#include "cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
/*
|
||||
* Short options for cpio. Please keep this sorted.
|
||||
@@ -347,9 +350,10 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
|
||||
owner->gid = pwent->pw_gid;
|
||||
} else {
|
||||
char *end;
|
||||
unsigned long val;
|
||||
errno = 0;
|
||||
owner->uid = (int)strtoul(user, &end, 10);
|
||||
if (errno || *end != '\0') {
|
||||
val = strtoul(user, &end, 10);
|
||||
if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
|
||||
snprintf(errbuff, sizeof(errbuff),
|
||||
"Couldn't lookup user ``%s''", user);
|
||||
errbuff[sizeof(errbuff) - 1] = '\0';
|
||||
@@ -357,6 +361,7 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
|
||||
*errmsg = errbuff;
|
||||
return (-1);
|
||||
}
|
||||
owner->uid = (int)val;
|
||||
}
|
||||
free(user);
|
||||
}
|
||||
@@ -373,15 +378,17 @@ owner_parse(const char *spec, struct cpio_owner *owner, const char **errmsg)
|
||||
}
|
||||
} else {
|
||||
char *end;
|
||||
unsigned long val;
|
||||
errno = 0;
|
||||
owner->gid = (int)strtoul(g, &end, 10);
|
||||
if (errno || *end != '\0') {
|
||||
val = strtoul(g, &end, 10);
|
||||
if (errno || *end != '\0' || val > (unsigned)INT_MAX) {
|
||||
snprintf(errbuff, sizeof(errbuff),
|
||||
"Couldn't lookup group ``%s''", g);
|
||||
errbuff[sizeof(errbuff) - 1] = '\0';
|
||||
*errmsg = errbuff;
|
||||
return (-1);
|
||||
}
|
||||
owner->gid = (int)val;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
|
||||
+86
-61
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "cpio_platform.h"
|
||||
|
||||
#include "lafe_getline.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
@@ -33,6 +35,9 @@
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_PWD_H
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
@@ -60,7 +65,7 @@
|
||||
#endif
|
||||
|
||||
#include "cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
#include "line_reader.h"
|
||||
#include "passphrase.h"
|
||||
|
||||
@@ -83,7 +88,7 @@ struct name_cache {
|
||||
|
||||
static int extract_data(struct archive *, struct archive *);
|
||||
const char * cpio_i64toa(int64_t);
|
||||
static const char *cpio_rename(const char *name);
|
||||
static void cpio_rename(struct archive_entry *);
|
||||
static int entry_to_archive(struct cpio *, struct archive_entry *);
|
||||
static int file_to_archive(struct cpio *, const char *);
|
||||
static void free_cache(struct name_cache *cache);
|
||||
@@ -110,27 +115,32 @@ static void passphrase_free(char *);
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
static char buff[16384];
|
||||
struct cpio _cpio; /* Allocated on stack. */
|
||||
struct cpio *cpio;
|
||||
struct cpio_owner owner;
|
||||
const char *errmsg;
|
||||
char *tptr;
|
||||
int opt, t;
|
||||
int opt;
|
||||
long t;
|
||||
|
||||
cpio = &_cpio;
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
cpio->buff = buff;
|
||||
cpio->buff_size = sizeof(buff);
|
||||
|
||||
|
||||
#if defined(HAVE_SIGACTION) && defined(SIGPIPE)
|
||||
{ /* Ignore SIGPIPE signals. */
|
||||
#if defined(HAVE_SIGACTION)
|
||||
{
|
||||
struct sigaction sa;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
#ifdef SIGPIPE
|
||||
/* Ignore SIGPIPE signals. */
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
/* Do not ignore SIGCHLD. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -196,13 +206,13 @@ main(int argc, char *argv[])
|
||||
case 'C': /* NetBSD/OpenBSD */
|
||||
errno = 0;
|
||||
tptr = NULL;
|
||||
t = (int)strtol(cpio->argument, &tptr, 10);
|
||||
if (errno || t <= 0 || *(cpio->argument) == '\0' ||
|
||||
t = strtol(cpio->argument, &tptr, 10);
|
||||
if (errno || t <= 0 || t > INT_MAX || *(cpio->argument) == '\0' ||
|
||||
tptr == NULL || *tptr != '\0') {
|
||||
lafe_errc(1, 0, "Invalid blocksize: %s",
|
||||
cpio->argument);
|
||||
}
|
||||
cpio->bytes_per_block = t;
|
||||
cpio->bytes_per_block = (int)t;
|
||||
break;
|
||||
case 'c': /* POSIX 1997 */
|
||||
cpio->format = "odc";
|
||||
@@ -214,7 +224,7 @@ main(int argc, char *argv[])
|
||||
if (archive_match_include_pattern_from_file(
|
||||
cpio->matching, cpio->argument,
|
||||
cpio->option_null) != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "Error : %s",
|
||||
lafe_errc(1, 0, "%s",
|
||||
archive_error_string(cpio->matching));
|
||||
break;
|
||||
case 'F': /* NetBSD/OpenBSD/GNU cpio */
|
||||
@@ -223,7 +233,7 @@ main(int argc, char *argv[])
|
||||
case 'f': /* POSIX 1997 */
|
||||
if (archive_match_exclude_pattern(cpio->matching,
|
||||
cpio->argument) != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "Error : %s",
|
||||
lafe_errc(1, 0, "%s",
|
||||
archive_error_string(cpio->matching));
|
||||
break;
|
||||
case OPTION_GRZIP:
|
||||
@@ -239,7 +249,7 @@ main(int argc, char *argv[])
|
||||
cpio->filename = cpio->argument;
|
||||
break;
|
||||
case 'i': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
if (cpio->mode != '\0' && cpio->mode != opt)
|
||||
lafe_errc(1, 0,
|
||||
"Cannot use both -i and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
@@ -281,13 +291,13 @@ main(int argc, char *argv[])
|
||||
cpio->filename = cpio->argument;
|
||||
break;
|
||||
case 'o': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
if (cpio->mode != '\0' && cpio->mode != opt)
|
||||
lafe_errc(1, 0,
|
||||
"Cannot use both -o and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
break;
|
||||
case 'p': /* POSIX 1997 */
|
||||
if (cpio->mode != '\0')
|
||||
if (cpio->mode != '\0' && cpio->mode != opt)
|
||||
lafe_errc(1, 0,
|
||||
"Cannot use both -p and -%c", cpio->mode);
|
||||
cpio->mode = opt;
|
||||
@@ -308,17 +318,21 @@ main(int argc, char *argv[])
|
||||
if (owner_parse(cpio->argument, &owner, &errmsg) != 0) {
|
||||
if (!errmsg)
|
||||
errmsg = "Error parsing owner";
|
||||
lafe_warnc(-1, "%s", errmsg);
|
||||
lafe_warnc(0, "%s", errmsg);
|
||||
usage();
|
||||
}
|
||||
if (owner.uid != -1)
|
||||
cpio->uid_override = owner.uid;
|
||||
if (owner.uname != NULL)
|
||||
if (owner.uname != NULL) {
|
||||
free(cpio->uname_override);
|
||||
cpio->uname_override = owner.uname;
|
||||
}
|
||||
if (owner.gid != -1)
|
||||
cpio->gid_override = owner.gid;
|
||||
if (owner.gname != NULL)
|
||||
if (owner.gname != NULL) {
|
||||
free(cpio->gname_override);
|
||||
cpio->gname_override = owner.gname;
|
||||
}
|
||||
break;
|
||||
case 'r': /* POSIX 1997 */
|
||||
cpio->option_rename = 1;
|
||||
@@ -401,7 +415,7 @@ main(int argc, char *argv[])
|
||||
while (*cpio->argv != NULL) {
|
||||
if (archive_match_include_pattern(cpio->matching,
|
||||
*cpio->argv) != ARCHIVE_OK)
|
||||
lafe_errc(1, 0, "Error : %s",
|
||||
lafe_errc(1, 0, "%s",
|
||||
archive_error_string(cpio->matching));
|
||||
--cpio->argc;
|
||||
++cpio->argv;
|
||||
@@ -419,7 +433,7 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
default:
|
||||
lafe_errc(1, 0,
|
||||
"Must specify at least one of -i, -o, or -p");
|
||||
"Must specify one of -i, -o, or -p");
|
||||
}
|
||||
|
||||
archive_match_free(cpio->matching);
|
||||
@@ -516,7 +530,7 @@ mode_out(struct cpio *cpio)
|
||||
int r;
|
||||
|
||||
if (cpio->option_append)
|
||||
lafe_errc(1, 0, "Append mode not yet supported.");
|
||||
lafe_errc(1, 0, "Append mode not yet supported");
|
||||
|
||||
cpio->archive_read_disk = archive_read_disk_new();
|
||||
if (cpio->archive_read_disk == NULL)
|
||||
@@ -630,7 +644,7 @@ mode_out(struct cpio *cpio)
|
||||
int64_t blocks =
|
||||
(archive_filter_bytes(cpio->archive, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
fprintf(stderr, "%lld %s\n", (long long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
}
|
||||
archive_write_free(cpio->archive);
|
||||
@@ -688,7 +702,6 @@ remove_leading_slash(const char *p)
|
||||
static int
|
||||
file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
{
|
||||
const char *destpath;
|
||||
struct archive_entry *entry, *spare;
|
||||
size_t len;
|
||||
int r;
|
||||
@@ -717,7 +730,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);
|
||||
@@ -730,7 +743,6 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
* pass mode or the name that will go into the archive in
|
||||
* output mode.
|
||||
*/
|
||||
destpath = srcpath;
|
||||
if (cpio->destdir) {
|
||||
len = cpio->destdir_len + strlen(srcpath) + 8;
|
||||
if (len >= cpio->pass_destpath_alloc) {
|
||||
@@ -746,15 +758,17 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
||||
}
|
||||
strcpy(cpio->pass_destpath, cpio->destdir);
|
||||
strcat(cpio->pass_destpath, remove_leading_slash(srcpath));
|
||||
destpath = cpio->pass_destpath;
|
||||
archive_entry_set_pathname(entry, cpio->pass_destpath);
|
||||
} else {
|
||||
archive_entry_set_pathname(entry, srcpath);
|
||||
}
|
||||
if (cpio->option_rename)
|
||||
destpath = cpio_rename(destpath);
|
||||
if (destpath == NULL) {
|
||||
cpio_rename(entry);
|
||||
|
||||
if (archive_entry_pathname(entry) == NULL) {
|
||||
archive_entry_free(entry);
|
||||
return (0);
|
||||
}
|
||||
archive_entry_copy_pathname(entry, destpath);
|
||||
|
||||
/*
|
||||
* If we're trying to preserve hardlinks, match them here.
|
||||
@@ -783,7 +797,6 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
const char *destpath = archive_entry_pathname(entry);
|
||||
const char *srcpath = archive_entry_sourcepath(entry);
|
||||
int fd = -1;
|
||||
ssize_t bytes_read;
|
||||
int r;
|
||||
|
||||
/* Print out the destination name to the user. */
|
||||
@@ -861,21 +874,23 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
|
||||
exit(1);
|
||||
|
||||
if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) {
|
||||
bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size);
|
||||
static char buff[16384];
|
||||
ssize_t bytes_read;
|
||||
|
||||
bytes_read = read(fd, buff, sizeof(buff));
|
||||
while (bytes_read > 0) {
|
||||
ssize_t bytes_write;
|
||||
bytes_write = archive_write_data(cpio->archive,
|
||||
cpio->buff, bytes_read);
|
||||
buff, bytes_read);
|
||||
if (bytes_write < 0)
|
||||
lafe_errc(1, archive_errno(cpio->archive),
|
||||
"%s", archive_error_string(cpio->archive));
|
||||
if (bytes_write < bytes_read) {
|
||||
lafe_warnc(0,
|
||||
"Truncated write; file may have "
|
||||
"grown while being archived.");
|
||||
"grown while being archived");
|
||||
}
|
||||
bytes_read = read(fd, cpio->buff,
|
||||
(unsigned)cpio->buff_size);
|
||||
bytes_read = read(fd, buff, sizeof(buff));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -987,12 +1002,13 @@ mode_in(struct cpio *cpio)
|
||||
lafe_errc(1, archive_errno(a),
|
||||
"%s", archive_error_string(a));
|
||||
}
|
||||
if (archive_match_path_excluded(cpio->matching, entry))
|
||||
r = archive_match_path_excluded(cpio->matching, entry);
|
||||
if (r < 0)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(cpio->matching));
|
||||
if (r)
|
||||
continue;
|
||||
if (cpio->option_rename) {
|
||||
destpath = cpio_rename(archive_entry_pathname(entry));
|
||||
archive_entry_set_pathname(entry, destpath);
|
||||
} else
|
||||
if (cpio->option_rename)
|
||||
cpio_rename(entry);
|
||||
destpath = archive_entry_pathname(entry);
|
||||
if (destpath == NULL)
|
||||
continue;
|
||||
@@ -1032,7 +1048,7 @@ mode_in(struct cpio *cpio)
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
fprintf(stderr, "%lld %s\n", (long long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
}
|
||||
archive_read_free(a);
|
||||
@@ -1104,7 +1120,10 @@ mode_list(struct cpio *cpio)
|
||||
lafe_errc(1, archive_errno(a),
|
||||
"%s", archive_error_string(a));
|
||||
}
|
||||
if (archive_match_path_excluded(cpio->matching, entry))
|
||||
r = archive_match_path_excluded(cpio->matching, entry);
|
||||
if (r < 0)
|
||||
lafe_errc(1, 0, "%s", archive_error_string(cpio->matching));
|
||||
if (r)
|
||||
continue;
|
||||
if (cpio->verbose)
|
||||
list_item_verbose(cpio, entry);
|
||||
@@ -1117,7 +1136,7 @@ mode_list(struct cpio *cpio)
|
||||
if (!cpio->quiet) {
|
||||
int64_t blocks = (archive_filter_bytes(a, 0) + 511)
|
||||
/ 512;
|
||||
fprintf(stderr, "%lu %s\n", (unsigned long)blocks,
|
||||
fprintf(stderr, "%lld %s\n", (long long)blocks,
|
||||
blocks == 1 ? "block" : "blocks");
|
||||
}
|
||||
archive_read_free(a);
|
||||
@@ -1284,54 +1303,60 @@ mode_pass(struct cpio *cpio, const char *destdir)
|
||||
* that an input of '.' means the name should be unchanged. GNU cpio
|
||||
* treats '.' as a literal new name.
|
||||
*/
|
||||
static const char *
|
||||
cpio_rename(const char *name)
|
||||
void
|
||||
cpio_rename(struct archive_entry *entry)
|
||||
{
|
||||
static char buff[1024];
|
||||
char *buff = NULL, *p, *ret = NULL;
|
||||
FILE *t;
|
||||
char *p, *ret;
|
||||
size_t n = 0;
|
||||
ssize_t r;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
FILE *to;
|
||||
|
||||
t = fopen("CONIN$", "r");
|
||||
if (t == NULL)
|
||||
return (name);
|
||||
return;
|
||||
to = fopen("CONOUT$", "w");
|
||||
if (to == NULL) {
|
||||
fclose(t);
|
||||
return (name);
|
||||
return;
|
||||
}
|
||||
fprintf(to, "%s (Enter/./(new name))? ", name);
|
||||
fprintf(to, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
|
||||
fclose(to);
|
||||
#else
|
||||
t = fopen("/dev/tty", "r+");
|
||||
if (t == NULL)
|
||||
return (name);
|
||||
fprintf(t, "%s (Enter/./(new name))? ", name);
|
||||
return;
|
||||
fprintf(t, "%s (Enter/./(new name))? ", archive_entry_pathname(entry));
|
||||
fflush(t);
|
||||
#endif
|
||||
|
||||
p = fgets(buff, sizeof(buff), t);
|
||||
r = getline(&buff, &n, t);
|
||||
fclose(t);
|
||||
if (p == NULL)
|
||||
if (r < 1)
|
||||
/* End-of-file is a blank line. */
|
||||
return (NULL);
|
||||
goto done;
|
||||
p = buff;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
++p;
|
||||
if (*p == '\n' || *p == '\0')
|
||||
/* Empty line. */
|
||||
return (NULL);
|
||||
if (*p == '.' && p[1] == '\n')
|
||||
goto done;
|
||||
if (*p == '.' && p[1] == '\n') {
|
||||
/* Single period preserves original name. */
|
||||
return (name);
|
||||
free(buff);
|
||||
return;
|
||||
}
|
||||
ret = p;
|
||||
/* Trim the final newline. */
|
||||
while (*p != '\0' && *p != '\n')
|
||||
++p;
|
||||
/* Overwrite the final \n with a null character. */
|
||||
*p = '\0';
|
||||
return (ret);
|
||||
done:
|
||||
archive_entry_set_pathname(entry, ret);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -71,8 +71,6 @@ struct cpio {
|
||||
|
||||
/* Work data. */
|
||||
struct archive *matching;
|
||||
char *buff;
|
||||
size_t buff_size;
|
||||
char *ppbuff;
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@
|
||||
#include <sddl.h>
|
||||
|
||||
#include "cpio.h"
|
||||
#include "err.h"
|
||||
#include "lafe_err.h"
|
||||
|
||||
#define EPOC_TIME (116444736000000000ULL)
|
||||
|
||||
@@ -140,7 +140,7 @@ cpio_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
CREATEFILE2_EXTENDED_PARAMETERS createExParams;
|
||||
#endif
|
||||
|
||||
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
|
||||
#if WINAPI_FAMILY_PARTITION (WINAPI_PARTITION_DESKTOP)
|
||||
handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
|
||||
lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
|
||||
hTemplateFile);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
IF(ENABLE_CPIO AND ENABLE_TEST)
|
||||
SET(bsdcpio_test_SOURCES
|
||||
../cmdline.c
|
||||
../../libarchive_fe/err.c
|
||||
../../libarchive_fe/lafe_err.c
|
||||
../../test_utils/test_utils.c
|
||||
../../test_utils/test_main.c
|
||||
test.h
|
||||
@@ -84,25 +84,12 @@ IF(ENABLE_CPIO AND ENABLE_TEST)
|
||||
# Generate list.h by grepping DEFINE_TEST() lines out of the C sources.
|
||||
#
|
||||
GENERATE_LIST_H(${CMAKE_CURRENT_BINARY_DIR}/list.h
|
||||
${CMAKE_CURRENT_LIST_FILE} ${bsdcpio_test_SOURCES})
|
||||
${CMAKE_CURRENT_LIST_FILE} bsdcpio_test ${bsdcpio_test_SOURCES})
|
||||
SET_PROPERTY(DIRECTORY APPEND PROPERTY INCLUDE_DIRECTORIES
|
||||
${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# list.h has a line DEFINE_TEST(testname) for every
|
||||
# test. We can use that to define the tests for cmake by
|
||||
# defining a DEFINE_TEST macro and reading list.h in.
|
||||
MACRO (DEFINE_TEST _testname)
|
||||
ADD_TEST(
|
||||
NAME bsdcpio_${_testname}
|
||||
COMMAND bsdcpio_test -vv
|
||||
-p $<TARGET_FILE:bsdcpio>
|
||||
-r ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-s
|
||||
${_testname})
|
||||
SET_TESTS_PROPERTIES(bsdcpio_${_testname} PROPERTIES SKIP_RETURN_CODE 2)
|
||||
ENDMACRO (DEFINE_TEST _testname)
|
||||
DISCOVER_TESTS(bsdcpio ${bsdcpio_test_SOURCES})
|
||||
|
||||
INCLUDE(${CMAKE_CURRENT_BINARY_DIR}/list.h)
|
||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/test_utils)
|
||||
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/cpio/test)
|
||||
|
||||
Loaded 100 of 630 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user