mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-30 12:25:10 +01:00
Compare commits
91
Commits
stable/14
...
releng/14.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16a79708d0 | ||
|
|
6a0d914d9c | ||
|
|
3447fea352 | ||
|
|
f3ffa7eb38 | ||
|
|
722746b39e | ||
|
|
0781dd1545 | ||
|
|
c0979bd273 | ||
|
|
168703212b | ||
|
|
d9352700f9 | ||
|
|
49b07b9466 | ||
|
|
ca1f7650a8 | ||
|
|
89104be0dd | ||
|
|
c5feebf383 | ||
|
|
89a2823e17 | ||
|
|
1eb03b059e | ||
|
|
23d06bb83d | ||
|
|
862cd6b8fa | ||
|
|
4651d400f1 | ||
|
|
700e7384df | ||
|
|
2c5831b304 | ||
|
|
ac2cbb46b5 | ||
|
|
4b8a2f7165 | ||
|
|
1920babc31 | ||
|
|
3ae196925d | ||
|
|
a1e3ff6580 | ||
|
|
c55000e7c2 | ||
|
|
faa47d299a | ||
|
|
1f3cea9cc1 | ||
|
|
4985615090 | ||
|
|
b9149a3af7 | ||
|
|
71bf983f92 | ||
|
|
10f8a9df52 | ||
|
|
c8918d6c74 | ||
|
|
5395ddd7aa | ||
|
|
af96dc44e1 | ||
|
|
42d33f9299 | ||
|
|
c5b8ed13c9 | ||
|
|
cce4df8b3c | ||
|
|
03c07bdc8b | ||
|
|
80b9b4dacd | ||
|
|
5252ae96ad | ||
|
|
dc647e4df9 | ||
|
|
8c6df7ead1 | ||
|
|
de5496958c | ||
|
|
8b0dcdec41 | ||
|
|
bcd5f95735 | ||
|
|
c16d0924db | ||
|
|
f0bfc02cba | ||
|
|
0aeaf495ba | ||
|
|
9513b68501 | ||
|
|
2594b7675a | ||
|
|
8a688fcc24 | ||
|
|
19d23cb8ac | ||
|
|
300d034b3c | ||
|
|
56f0fc0011 | ||
|
|
b8276743e4 | ||
|
|
d86dcfc648 | ||
|
|
57921ae825 | ||
|
|
0ff73c7796 | ||
|
|
a30127914a | ||
|
|
0be04cb5cb | ||
|
|
35874d28c8 | ||
|
|
a0bc4ec08b | ||
|
|
2a6bd6e37b | ||
|
|
bb6af83fe4 | ||
|
|
33197f22b5 | ||
|
|
ea310d18b2 | ||
|
|
b658d3ea49 | ||
|
|
c5fc8587ab | ||
|
|
0d2b7892cd | ||
|
|
a4c23ad430 | ||
|
|
f675d2bb34 | ||
|
|
a231e29907 | ||
|
|
d0dcee46d9 | ||
|
|
bc01ae40e4 | ||
|
|
58e70f39fd | ||
|
|
2bc5b1d605 | ||
|
|
0015947451 | ||
|
|
a752de91d0 | ||
|
|
ac2e98ed57 | ||
|
|
3166167784 | ||
|
|
1db6ffb2a4 | ||
|
|
4b4c7b1924 | ||
|
|
aeba4bd10f | ||
|
|
193a9943ba | ||
|
|
28b881840d | ||
|
|
98ed0edd1a | ||
|
|
c90ebd3fa3 | ||
|
|
574e7bad4a | ||
|
|
ce99ca6967 | ||
|
|
603608e520 |
No files matched your search
+1
-1
@@ -4,7 +4,7 @@ compute_engine_instance:
|
||||
# gcloud compute images list --project freebsd-org-cloud-dev --no-standard-images
|
||||
platform: freebsd
|
||||
image_project: freebsd-org-cloud-dev
|
||||
image: freebsd-13-2-release-amd64
|
||||
image: freebsd-13-3-release-amd64
|
||||
cpu: 8
|
||||
memory: 8G
|
||||
disk: 40
|
||||
|
||||
@@ -51,6 +51,26 @@
|
||||
# xargs -n1 | sort | uniq -d;
|
||||
# done
|
||||
|
||||
# 20250310: caroot bundle updated
|
||||
OLD_FILES+=usr/share/certs/trusted/Entrust_Root_Certification_Authority_-_G4.pem
|
||||
OLD_FILES+=usr/share/certs/trusted/SecureSign_RootCA11.pem
|
||||
OLD_FILES+=usr/share/certs/trusted/Security_Communication_RootCA3.pem
|
||||
OLD_FILES+=usr/share/certs/trusted/SwissSign_Silver_CA_-_G2.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/AddTrust_External_Root.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/AddTrust_Low-Value_Services_Root.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Staat_der_Nederlanden_Root_CA_-_G2.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Cybertrust_Global_Root.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/DST_Root_CA_X3.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/GlobalSign_Root_CA_-_R2.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/QuoVadis_Root_CA.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Sonera_Class_2_Root_CA.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/GeoTrust_Global_CA.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Staat_der_Nederlanden_EV_Root_CA.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/E-Tugra_Certification_Authority.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Hongkong_Post_Root_CA_1.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Security_Communication_Root_CA.pem
|
||||
OLD_FILES+=usr/share/certs/untrusted/Trustis_FPS_Root_CA.pem
|
||||
|
||||
# 20240914 libpcap upgrade from 1.10.4 to 1.10.5
|
||||
OLD_FILES+=contrib/libpcap/pcap-haiku.cpp
|
||||
OLD_FILES+=contrib/libpcap/pcap-rpcap-int.h
|
||||
|
||||
@@ -12,6 +12,85 @@ Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before updating system packages
|
||||
and/or ports.
|
||||
|
||||
20250930:
|
||||
14.2-RELEASE-p7 EN-25:18.freebsd-update
|
||||
SA-25:08.openssl
|
||||
|
||||
Fix freebsd-update(8) installing libraries in incorrect order. [EN-25:18.freebsd-update]
|
||||
|
||||
Fix multiple vulnerabilities in OpenSSL. [SA-25:08.openssl]
|
||||
|
||||
20250916:
|
||||
14.2-RELEASE-p6 EN-25:15.arm64
|
||||
|
||||
Fix arm64 syscall(2) allows unprivileged user to panic kernel. [EN-25:15.arm64]
|
||||
|
||||
20250808:
|
||||
14.2-RELEASE-p5 EN-25:14.route
|
||||
SA-25:07.libarchive
|
||||
|
||||
Fix route(8) monitor buffering too much when redirected to a
|
||||
file. [EN-25:14.route]
|
||||
|
||||
Update libarchive to 3.8.1 to fix integer overflow leading to double
|
||||
free. [SA-25:07.libarchive]
|
||||
|
||||
20250702:
|
||||
14.2-RELEASE-p4 EN-25:09.libc
|
||||
EN-25:10.zfs
|
||||
EN-25:11.ena
|
||||
SA-25:06.xz
|
||||
|
||||
Fix dynamically-loaded C++ libraries crashing at exit [EN-25:09.libc]
|
||||
|
||||
Fix corruption in ZFS replication streams from encrypted datasets [EN-25:10.zfs]
|
||||
|
||||
Fix ena resets and kernel panic on Nitro v4 or newer instances [EN-25:11.ena]
|
||||
|
||||
Fix use-after-free in multi-threaded xz decoder [SA-25:06.xz]
|
||||
|
||||
20250410:
|
||||
14.2-RELEASE-p3 EN-25:04.tzdata
|
||||
EN-25:05.expat
|
||||
EN-25:06.daemon
|
||||
EN-25:07.openssl
|
||||
EN-25:08.caroot
|
||||
|
||||
Timezone database information update [EN-25:04.tzdata]
|
||||
|
||||
Update expat to 2.7.1 [EN-25:05.expat]
|
||||
|
||||
daemon(8) missing signals [EN-25:06.daemon]
|
||||
|
||||
Update OpenSSL to 3.0.16 [EN-25:07.openssl]
|
||||
|
||||
Root certificate bundle update [EN-25:08.caroot]
|
||||
|
||||
20250221:
|
||||
14.2-RELEASE-p2 SA-25:05.openssh
|
||||
|
||||
Multiple vulnerabilities in OpenSSH [SA-25:05.openssh]
|
||||
|
||||
20250129:
|
||||
14.2-RELEASE-p1 SA-25:02.fs
|
||||
SA-25:03.etcupdate
|
||||
SA-25:04.ktrace
|
||||
EN-25:02.audit
|
||||
EN-25:03.tzdata
|
||||
|
||||
Buffer overflow in some filesystems via NFS [SA-25:02.fs]
|
||||
|
||||
Unprivileged access to system files [SA-25:03.etcupdate]
|
||||
|
||||
Uninitialized kernel memory disclosure via ktrace(2) [SA-25:04.ktrace]
|
||||
|
||||
System call auditing disabled by DTrace [EN-25:02.audit]
|
||||
|
||||
Timezone database information update [EN-25:03.tzdata]
|
||||
|
||||
20241203:
|
||||
14.2-RELEASE.
|
||||
|
||||
20240419:
|
||||
Clang, llvm, lld, lldb, compiler-rt, libc++, libunwind and openmp have
|
||||
been upgraded to 18.1.6. It is important that you run `make delete-old`
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
|
||||
Copyright (c) 2001-2022 Expat maintainers
|
||||
Copyright (c) 2001-2025 Expat maintainers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
||||
+283
-3
@@ -1,6 +1,286 @@
|
||||
NOTE: We are looking for help with a few things:
|
||||
https://github.com/libexpat/libexpat/labels/help%20wanted
|
||||
If you can help, please get in touch. Thanks!
|
||||
__ __ _
|
||||
___\ \/ /_ __ __ _| |_
|
||||
/ _ \\ /| '_ \ / _` | __|
|
||||
| __// \| |_) | (_| | |_
|
||||
\___/_/\_\ .__/ \__,_|\__|
|
||||
|_| XML parser
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! <blink>Expat is UNDERSTAFFED and WITHOUT FUNDING.</blink> !!
|
||||
!! ~~~~~~~~~~~~ !!
|
||||
!! The following topics need *additional skilled C developers* to progress !!
|
||||
!! in a timely manner or at all (loosely ordered by descending priority): !!
|
||||
!! !!
|
||||
!! - teaming up on researching and fixing future security reports and !!
|
||||
!! ClusterFuzz findings with few-days-max response times in communication !!
|
||||
!! in order to (1) have a sound fix ready before the end of a 90 days !!
|
||||
!! grace period and (2) in a sustainable manner, !!
|
||||
!! - helping CPython Expat bindings with supporting Expat's billion laughs !!
|
||||
!! attack protection API (https://github.com/python/cpython/issues/90949): !!
|
||||
!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !!
|
||||
!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !!
|
||||
!! - helping Perl's XML::Parser Expat bindings with supporting Expat's !!
|
||||
!! security API (https://github.com/cpan-authors/XML-Parser/issues/102): !!
|
||||
!! - XML_SetBillionLaughsAttackProtectionActivationThreshold !!
|
||||
!! - XML_SetBillionLaughsAttackProtectionMaximumAmplification !!
|
||||
!! - XML_SetReparseDeferralEnabled !!
|
||||
!! - implementing and auto-testing XML 1.0r5 support !!
|
||||
!! (needs discussion before pull requests), !!
|
||||
!! - smart ideas on fixing the Autotools CMake files generation issue !!
|
||||
!! without breaking CI (needs discussion before pull requests), !!
|
||||
!! - pushing migration from `int` to `size_t` further !!
|
||||
!! including edge-cases test coverage (needs discussion before anything). !!
|
||||
!! !!
|
||||
!! For details, please reach out via e-mail to [email protected] so we !!
|
||||
!! can schedule a voice call on the topic, in English or German. !!
|
||||
!! !!
|
||||
!! THANK YOU! Sebastian Pipping -- Berlin, 2024-03-09 !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
Release 2.7.1 Thu March 27 2025
|
||||
Bug fixes:
|
||||
#980 #989 Restore event pointer behavior from Expat 2.6.4
|
||||
(that the fix to CVE-2024-8176 changed in 2.7.0);
|
||||
affected API functions are:
|
||||
- XML_GetCurrentByteCount
|
||||
- XML_GetCurrentByteIndex
|
||||
- XML_GetCurrentColumnNumber
|
||||
- XML_GetCurrentLineNumber
|
||||
- XML_GetInputContext
|
||||
|
||||
Other changes:
|
||||
#976 #977 Autotools: Integrate files "fuzz/xml_lpm_fuzzer.{cpp,proto}"
|
||||
with Automake that were missing from 2.7.0 release tarballs
|
||||
#983 #984 Fix printf format specifiers for 32bit Emscripten
|
||||
#992 docs: Promote OpenSSF Best Practices self-certification
|
||||
#978 tests/benchmark: Resolve mistaken double close
|
||||
#986 Address compiler warnings
|
||||
#990 #993 Version info bumped from 11:1:10 (libexpat*.so.1.10.1)
|
||||
to 11:2:10 (libexpat*.so.1.10.2); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Infrastructure:
|
||||
#982 CI: Start running Perl XML::Parser integration tests
|
||||
#987 CI: Enforce Clang Static Analyzer clean code
|
||||
#991 CI: Re-enable warning clang-analyzer-valist.Uninitialized
|
||||
for clang-tidy
|
||||
#981 CI: Cover compilation with musl
|
||||
#983 #984 CI: Cover compilation with 32bit Emscripten
|
||||
#976 #977 CI: Protect against fuzzer files missing from future
|
||||
release archives
|
||||
|
||||
Special thanks to:
|
||||
Berkay Eren Ürün
|
||||
Matthew Fernandez
|
||||
and
|
||||
Perl XML::Parser
|
||||
|
||||
Release 2.7.0 Thu March 13 2025
|
||||
Security fixes:
|
||||
#893 #973 CVE-2024-8176 -- Fix crash from chaining a large number
|
||||
of entities caused by stack overflow by resolving use of
|
||||
recursion, for all three uses of entities:
|
||||
- general entities in character data ("<e>&g1;</e>")
|
||||
- general entities in attribute values ("<e k1='&g1;'/>")
|
||||
- parameter entities ("%p1;")
|
||||
Known impact is (reliable and easy) denial of service:
|
||||
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H/E:H/RL:O/RC:C
|
||||
(Base Score: 7.5, Temporal Score: 7.2)
|
||||
Please note that a layer of compression around XML can
|
||||
significantly reduce the minimum attack payload size.
|
||||
|
||||
Other changes:
|
||||
#935 #937 Autotools: Make generated CMake files look for
|
||||
libexpat.@[email protected] on macOS
|
||||
#925 Autotools: Sync CMake templates with CMake 3.29
|
||||
#945 #962 #966 CMake: Drop support for CMake <3.13
|
||||
#942 CMake: Small fuzzing related improvements
|
||||
#921 docs: Add missing documentation of error code
|
||||
XML_ERROR_NOT_STARTED that was introduced with 2.6.4
|
||||
#941 docs: Document need for C++11 compiler for use from C++
|
||||
#959 tests/benchmark: Fix a (harmless) TOCTTOU
|
||||
#944 Windows: Fix installer target location of file xmlwf.xml
|
||||
for CMake
|
||||
#953 Windows: Address warning -Wunknown-warning-option
|
||||
about -Wno-pedantic-ms-format from LLVM MinGW
|
||||
#971 Address Cppcheck warnings
|
||||
#969 #970 Mass-migrate links from http:// to https://
|
||||
#947 #958 ..
|
||||
#974 #975 Document changes since the previous release
|
||||
#974 #975 Version info bumped from 11:0:10 (libexpat*.so.1.10.0)
|
||||
to 11:1:10 (libexpat*.so.1.10.1); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Infrastructure:
|
||||
#926 tests: Increase robustness
|
||||
#927 #932 ..
|
||||
#930 #933 tests: Increase test coverage
|
||||
#617 #950 ..
|
||||
#951 #952 ..
|
||||
#954 #955 .. Fuzzing: Add new fuzzer "xml_lpm_fuzzer" based on
|
||||
#961 Google's libprotobuf-mutator ("LPM")
|
||||
#957 Fuzzing|CI: Start producing fuzzing code coverage reports
|
||||
#936 CI: Pass -q -q for LCOV >=2.1 in coverage.sh
|
||||
#942 CI: Small fuzzing related improvements
|
||||
#139 #203 ..
|
||||
#791 #946 CI: Make GitHub Actions build using MSVC on Windows and
|
||||
produce 32bit and 64bit Windows binaries
|
||||
#956 CI: Get off of about-to-be-removed Ubuntu 20.04
|
||||
#960 #964 CI: Start uploading to Coverity Scan for static analysis
|
||||
#972 CI: Stop loading DTD from the internet to address flaky CI
|
||||
#971 CI: Adapt to breaking changes in Cppcheck
|
||||
|
||||
Special thanks to:
|
||||
Alexander Gieringer
|
||||
Berkay Eren Ürün
|
||||
Hanno Böck
|
||||
Jann Horn
|
||||
Mark Brand
|
||||
Sebastian Andrzej Siewior
|
||||
Snild Dolkow
|
||||
Thomas Pröll
|
||||
Tomas Korbar
|
||||
valord577
|
||||
and
|
||||
Google Project Zero
|
||||
Linutronix
|
||||
Red Hat
|
||||
Siemens
|
||||
|
||||
Release 2.6.4 Wed November 6 2024
|
||||
Security fixes:
|
||||
#915 CVE-2024-50602 -- Fix crash within function XML_ResumeParser
|
||||
from a NULL pointer dereference by disallowing function
|
||||
XML_StopParser to (stop or) suspend an unstarted parser.
|
||||
A new error code XML_ERROR_NOT_STARTED was introduced to
|
||||
properly communicate this situation. // CWE-476 CWE-754
|
||||
|
||||
Other changes:
|
||||
#903 CMake: Add alias target "expat::expat"
|
||||
#905 docs: Document use via CMake >=3.18 with FetchContent
|
||||
and SOURCE_SUBDIR and its consequences
|
||||
#902 tests: Reduce use of global parser instance
|
||||
#904 tests: Resolve duplicate handler
|
||||
#317 #918 tests: Improve tests on doctype closing (ex CVE-2019-15903)
|
||||
#914 Fix signedness of format strings
|
||||
#915 For use from C++, expat.h started requiring C++11 due to
|
||||
use of C99 features
|
||||
#919 #920 Version info bumped from 10:3:9 (libexpat*.so.1.9.3)
|
||||
to 11:0:10 (libexpat*.so.1.10.0); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Infrastructure:
|
||||
#907 CI: Upgrade Clang from 18 to 19
|
||||
#913 CI: Drop macos-12 and add macos-15
|
||||
#910 CI: Adapt to breaking changes in GitHub Actions
|
||||
#898 Add missing entries to .gitignore
|
||||
|
||||
Special thanks to:
|
||||
Hanno Böck
|
||||
José Eduardo Gutiérrez Conejo
|
||||
José Ricardo Cardona Quesada
|
||||
|
||||
Release 2.6.3 Wed September 4 2024
|
||||
Security fixes:
|
||||
#887 #890 CVE-2024-45490 -- Calling function XML_ParseBuffer with
|
||||
len < 0 without noticing and then calling XML_GetBuffer
|
||||
will have XML_ParseBuffer fail to recognize the problem
|
||||
and XML_GetBuffer corrupt memory.
|
||||
With the fix, XML_ParseBuffer now complains with error
|
||||
XML_ERROR_INVALID_ARGUMENT just like sibling XML_Parse
|
||||
has been doing since Expat 2.2.1, and now documented.
|
||||
Impact is denial of service to potentially artitrary code
|
||||
execution.
|
||||
#888 #891 CVE-2024-45491 -- Internal function dtdCopy can have an
|
||||
integer overflow for nDefaultAtts on 32-bit platforms
|
||||
(where UINT_MAX equals SIZE_MAX).
|
||||
Impact is denial of service to potentially artitrary code
|
||||
execution.
|
||||
#889 #892 CVE-2024-45492 -- Internal function nextScaffoldPart can
|
||||
have an integer overflow for m_groupSize on 32-bit
|
||||
platforms (where UINT_MAX equals SIZE_MAX).
|
||||
Impact is denial of service to potentially artitrary code
|
||||
execution.
|
||||
|
||||
Other changes:
|
||||
#851 #879 Autotools: Sync CMake templates with CMake 3.28
|
||||
#853 Autotools: Always provide path to find(1) for portability
|
||||
#861 Autotools: Ensure that the m4 directory always exists.
|
||||
#870 Autotools: Simplify handling of SIZEOF_VOID_P
|
||||
#869 Autotools: Support non-GNU sed
|
||||
#856 Autotools|CMake: Fix main() to main(void)
|
||||
#865 Autotools|CMake: Fix compile tests for HAVE_SYSCALL_GETRANDOM
|
||||
#863 Autotools|CMake: Stop requiring dos2unix
|
||||
#854 #855 CMake: Fix check for symbols size_t and off_t
|
||||
#864 docs|tests: Convert README to Markdown and update
|
||||
#741 Windows: Drop support for Visual Studio <=15.0/2017
|
||||
#886 Drop needless XML_DTD guards around is_param access
|
||||
#885 Fix typo in a code comment
|
||||
#894 #896 Version info bumped from 10:2:9 (libexpat*.so.1.9.2)
|
||||
to 10:3:9 (libexpat*.so.1.9.3); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Infrastructure:
|
||||
#880 Readme: Promote the call for help
|
||||
#868 CI: Fix various issues
|
||||
#849 CI: Allow triggering GitHub Actions workflows manually
|
||||
#851 #872 ..
|
||||
#873 #879 CI: Adapt to breaking changes in GitHub Actions
|
||||
|
||||
Special thanks to:
|
||||
Alexander Bluhm
|
||||
Berkay Eren Ürün
|
||||
Dag-Erling Smørgrav
|
||||
Ferenc Géczi
|
||||
TaiYou
|
||||
|
||||
Release 2.6.2 Wed March 13 2024
|
||||
Security fixes:
|
||||
#839 #842 CVE-2024-28757 -- Prevent billion laughs attacks with
|
||||
isolated use of external parsers. Please see the commit
|
||||
message of commit 1d50b80cf31de87750103656f6eb693746854aa8
|
||||
for details.
|
||||
|
||||
Bug fixes:
|
||||
#839 #841 Reject direct parameter entity recursion
|
||||
and avoid the related undefined behavior
|
||||
|
||||
Other changes:
|
||||
#847 Autotools: Fix build for DOCBOOK_TO_MAN containing spaces
|
||||
#837 Add missing #821 and #824 to 2.6.1 change log
|
||||
#838 #843 Version info bumped from 10:1:9 (libexpat*.so.1.9.1)
|
||||
to 10:2:9 (libexpat*.so.1.9.2); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Special thanks to:
|
||||
Philippe Antoine
|
||||
Tomas Korbar
|
||||
and
|
||||
Clang UndefinedBehaviorSanitizer
|
||||
OSS-Fuzz / ClusterFuzz
|
||||
|
||||
Release 2.6.1 Thu February 29 2024
|
||||
Bug fixes:
|
||||
#817 Make tests independent of CPU speed, and thus more robust
|
||||
#828 #836 Expose billion laughs API with XML_DTD defined and
|
||||
XML_GE undefined, regression from 2.6.0
|
||||
|
||||
Other changes:
|
||||
#829 Hide test-only code behind new internal macro
|
||||
#833 Autotools: Reject expat_config.h.in defining SIZEOF_VOID_P
|
||||
#821 #824 Autotools: Fix "make clean" for case:
|
||||
./configure --without-docbook && make clean all
|
||||
#819 Address compiler warnings
|
||||
#832 #834 Version info bumped from 10:0:9 (libexpat*.so.1.9.0)
|
||||
to 10:1:9 (libexpat*.so.1.9.1); see https://verbump.de/
|
||||
for what these numbers do
|
||||
|
||||
Infrastructure:
|
||||
#818 CI: Adapt to breaking changes in clang-format
|
||||
|
||||
Special thanks to:
|
||||
David Hall
|
||||
Snild Dolkow
|
||||
|
||||
Release 2.6.0 Tue February 6 2024
|
||||
Security fixes:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# $FreeBSD$
|
||||
*.MPW
|
||||
*.cmake
|
||||
*.def
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2023 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2025 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2018 KangLin <[email protected]>
|
||||
# Copyright (c) 2022 Johnny Jazeix <[email protected]>
|
||||
# Copyright (c) 2023 Sony Corporation / Snild Dolkow <[email protected]>
|
||||
# Copyright (c) 2024 Alexander Bluhm <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -94,6 +96,8 @@ EXTRA_DIST = \
|
||||
conftools/expat.m4 \
|
||||
conftools/get-version.sh \
|
||||
\
|
||||
fuzz/xml_lpm_fuzzer.cpp \
|
||||
fuzz/xml_lpm_fuzzer.proto \
|
||||
fuzz/xml_parsebuffer_fuzzer.c \
|
||||
fuzz/xml_parse_fuzzer.c \
|
||||
\
|
||||
@@ -114,10 +118,10 @@ buildlib:
|
||||
@echo 'ERROR: is no longer supported. INSTEAD please:' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
@echo 'ERROR: * Mass-patch Makefile.am, e.g.' >&2
|
||||
@echo 'ERROR: # find -name Makefile.am -exec sed \' >&2
|
||||
@echo 'ERROR: # find . -name Makefile.am -exec sed \' >&2
|
||||
@echo 'ERROR: -e "s,libexpat\.la,libexpatw.la," \' >&2
|
||||
@echo 'ERROR: -e "s,libexpat_la,libexpatw_la," \' >&2
|
||||
@echo 'ERROR: -i {} +' >&2
|
||||
@echo 'ERROR: -i.bak {} +' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
@echo 'ERROR: * Run automake to re-generate Makefile.in files' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2023 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2025 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2018 KangLin <[email protected]>
|
||||
# Copyright (c) 2022 Johnny Jazeix <[email protected]>
|
||||
# Copyright (c) 2023 Sony Corporation / Snild Dolkow <[email protected]>
|
||||
# Copyright (c) 2024 Alexander Bluhm <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -384,6 +386,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -397,7 +400,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
@@ -492,6 +494,8 @@ EXTRA_DIST = \
|
||||
conftools/expat.m4 \
|
||||
conftools/get-version.sh \
|
||||
\
|
||||
fuzz/xml_lpm_fuzzer.cpp \
|
||||
fuzz/xml_lpm_fuzzer.proto \
|
||||
fuzz/xml_parsebuffer_fuzzer.c \
|
||||
fuzz/xml_parse_fuzzer.c \
|
||||
\
|
||||
@@ -1080,10 +1084,10 @@ buildlib:
|
||||
@echo 'ERROR: is no longer supported. INSTEAD please:' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
@echo 'ERROR: * Mass-patch Makefile.am, e.g.' >&2
|
||||
@echo 'ERROR: # find -name Makefile.am -exec sed \' >&2
|
||||
@echo 'ERROR: # find . -name Makefile.am -exec sed \' >&2
|
||||
@echo 'ERROR: -e "s,libexpat\.la,libexpatw.la," \' >&2
|
||||
@echo 'ERROR: -e "s,libexpat_la,libexpatw_la," \' >&2
|
||||
@echo 'ERROR: -i {} +' >&2
|
||||
@echo 'ERROR: -i.bak {} +' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
@echo 'ERROR: * Run automake to re-generate Makefile.in files' >&2
|
||||
@echo 'ERROR:' >&2
|
||||
|
||||
+58
-17
@@ -3,9 +3,16 @@
|
||||
[](https://repology.org/metapackage/expat/versions)
|
||||
[](https://sourceforge.net/projects/expat/files/)
|
||||
[](https://github.com/libexpat/libexpat/releases)
|
||||
[](https://www.bestpractices.dev/projects/10205)
|
||||
|
||||
> [!CAUTION]
|
||||
>
|
||||
> Expat is **understaffed** and without funding.
|
||||
> There is a [call for help with details](https://github.com/libexpat/libexpat/blob/master/expat/Changes)
|
||||
> at the top of the `Changes` file.
|
||||
|
||||
|
||||
# Expat, Release 2.6.0
|
||||
# Expat, Release 2.7.1
|
||||
|
||||
This is Expat, a C99 library for parsing
|
||||
[XML 1.0 Fourth Edition](https://www.w3.org/TR/2006/REC-xml-20060816/), started by
|
||||
@@ -16,11 +23,11 @@ are called when the parser discovers the associated structures in the
|
||||
document being parsed. A start tag is an example of the kind of
|
||||
structures for which you may register handlers.
|
||||
|
||||
Expat supports the following compilers:
|
||||
Expat supports the following C99 compilers:
|
||||
|
||||
- GNU GCC >=4.5
|
||||
- GNU GCC >=4.5 (for use from C) or GNU GCC >=4.8.1 (for use from C++)
|
||||
- LLVM Clang >=3.5
|
||||
- Microsoft Visual Studio >=15.0/2017 (rolling `${today} minus 5 years`)
|
||||
- Microsoft Visual Studio >=16.0/2019 (rolling `${today} minus 5 years`)
|
||||
|
||||
Windows users can use the
|
||||
[`expat-win32bin-*.*.*.{exe,zip}` download](https://github.com/libexpat/libexpat/releases),
|
||||
@@ -37,16 +44,16 @@ This license is the same as the MIT/X Consortium license.
|
||||
|
||||
## Using libexpat in your CMake-Based Project
|
||||
|
||||
There are two ways of using libexpat with CMake:
|
||||
There are three documented ways of using libexpat with CMake:
|
||||
|
||||
### a) Module Mode
|
||||
### a) `find_package` with Module Mode
|
||||
|
||||
This approach leverages CMake's own [module `FindEXPAT`](https://cmake.org/cmake/help/latest/module/FindEXPAT.html).
|
||||
|
||||
Notice the *uppercase* `EXPAT` in the following example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.0) # or 3.10, see below
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
@@ -56,15 +63,10 @@ add_executable(hello
|
||||
hello.c
|
||||
)
|
||||
|
||||
# a) for CMake >=3.10 (see CMake's FindEXPAT docs)
|
||||
target_link_libraries(hello PUBLIC EXPAT::EXPAT)
|
||||
|
||||
# b) for CMake >=3.0
|
||||
target_include_directories(hello PRIVATE ${EXPAT_INCLUDE_DIRS})
|
||||
target_link_libraries(hello PUBLIC ${EXPAT_LIBRARIES})
|
||||
```
|
||||
|
||||
### b) Config Mode
|
||||
### b) `find_package` with Config Mode
|
||||
|
||||
This approach requires files from…
|
||||
|
||||
@@ -79,7 +81,7 @@ or
|
||||
Notice the *lowercase* `expat` in the following example:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
@@ -92,6 +94,45 @@ add_executable(hello
|
||||
target_link_libraries(hello PUBLIC expat::expat)
|
||||
```
|
||||
|
||||
### c) The `FetchContent` module
|
||||
|
||||
This approach — as demonstrated below — requires CMake >=3.18 for both the
|
||||
[`FetchContent` module](https://cmake.org/cmake/help/latest/module/FetchContent.html)
|
||||
and its support for the `SOURCE_SUBDIR` option to be available.
|
||||
|
||||
Please note that:
|
||||
- Use of the `FetchContent` module with *non-release* SHA1s or `master`
|
||||
of libexpat is neither advised nor considered officially supported.
|
||||
- Pinning to a specific commit is great for robust CI.
|
||||
- Pinning to a specific commit needs updating every time there is a new
|
||||
release of libexpat — either manually or through automation —,
|
||||
to not miss out on libexpat security updates.
|
||||
|
||||
For an example that pulls in libexpat via Git:
|
||||
|
||||
```cmake
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
project(hello VERSION 1.0.0)
|
||||
|
||||
FetchContent_Declare(
|
||||
expat
|
||||
GIT_REPOSITORY https://github.com/libexpat/libexpat/
|
||||
GIT_TAG 000000000_GIT_COMMIT_SHA1_HERE_000000000 # i.e. Git tag R_0_Y_Z
|
||||
SOURCE_SUBDIR expat/
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(expat)
|
||||
|
||||
add_executable(hello
|
||||
hello.c
|
||||
)
|
||||
|
||||
target_link_libraries(hello PUBLIC expat)
|
||||
```
|
||||
|
||||
|
||||
## Building from a Git Clone
|
||||
|
||||
@@ -158,10 +199,10 @@ support this mode of compilation (yet):
|
||||
|
||||
1. Mass-patch `Makefile.am` files to use `libexpatw.la` for a library name:
|
||||
<br/>
|
||||
`find -name Makefile.am -exec sed
|
||||
`find . -name Makefile.am -exec sed
|
||||
-e 's,libexpat\.la,libexpatw.la,'
|
||||
-e 's,libexpat_la,libexpatw_la,'
|
||||
-i {} +`
|
||||
-i.bak {} +`
|
||||
|
||||
1. Run `automake` to re-write `Makefile.in` files:<br/>
|
||||
`automake`
|
||||
@@ -250,7 +291,7 @@ EXPAT_ENABLE_INSTALL:BOOL=ON
|
||||
// Use /MT flag (static CRT) when compiling in MSVC
|
||||
EXPAT_MSVC_STATIC_CRT:BOOL=OFF
|
||||
|
||||
// Build fuzzers via ossfuzz for the expat library
|
||||
// Build fuzzers via OSS-Fuzz for the expat library
|
||||
EXPAT_OSSFUZZ_BUILD:BOOL=OFF
|
||||
|
||||
// Build a shared expat library
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#
|
||||
# Copyright (c) 2017-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2018 Marco Maggi <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -31,25 +32,4 @@
|
||||
|
||||
set -e
|
||||
|
||||
# File expat_config.h.in (as generated by autoheader by autoreconf) contains
|
||||
# macro SIZEOF_VOID_P which is (1) not really needed by Expat as of today and
|
||||
# (2) a problem to "multilib" systems with one shared installed
|
||||
# /usr/include/expat_config.h for two Expats with different "void *" sizes
|
||||
# installed in e.g. /usr/lib32 and /usr/lib64. Hence we patch macro
|
||||
# SIZEOF_VOID_P out of template expat_config.h.in so that configure will
|
||||
# not put SIZEOF_VOID_P in the eventual expat_config.h.
|
||||
patch_expat_config_h_in() {
|
||||
local filename="$1"
|
||||
local sizeof_void_p_line_number="$(grep -F -n SIZEOF_VOID_P "${filename}" | awk -F: '{print $1}')"
|
||||
[[ ${sizeof_void_p_line_number} =~ ^[0-9]+$ ]] # cheap assert
|
||||
local first_line_to_delete=$(( sizeof_void_p_line_number - 1 ))
|
||||
local last_line_to_delete=$(( sizeof_void_p_line_number + 1 ))
|
||||
# Note: Avoiding "sed -i" only for macOS portability.
|
||||
local tempfile="$(mktemp)"
|
||||
sed "${first_line_to_delete},${last_line_to_delete}d" "${filename}" > "${tempfile}"
|
||||
mv "${tempfile}" "${filename}"
|
||||
}
|
||||
|
||||
autoreconf --warnings=all --install --verbose "$@"
|
||||
|
||||
patch_expat_config_h_in expat_config.h.in
|
||||
exec autoreconf --warnings=all --install --verbose "$@"
|
||||
+31
-14
@@ -11,7 +11,7 @@ dnl Copyright (c) 2000 Clark Cooper <[email protected]>
|
||||
dnl Copyright (c) 2000-2005 Fred L. Drake, Jr. <[email protected]>
|
||||
dnl Copyright (c) 2001-2003 Greg Stein <[email protected]>
|
||||
dnl Copyright (c) 2006-2012 Karl Waclawek <[email protected]>
|
||||
dnl Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
|
||||
dnl Copyright (c) 2016-2025 Sebastian Pipping <[email protected]>
|
||||
dnl Copyright (c) 2017 S. P. Zeidler <[email protected]>
|
||||
dnl Copyright (c) 2017 Stephen Groat <[email protected]>
|
||||
dnl Copyright (c) 2017-2020 Joe Orton <[email protected]>
|
||||
@@ -22,6 +22,8 @@ dnl Copyright (c) 2018 KangLin <[email protected]>
|
||||
dnl Copyright (c) 2019 Mohammed Khajapasha <[email protected]>
|
||||
dnl Copyright (c) 2019 Kishore Kunche <[email protected]>
|
||||
dnl Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
||||
dnl Copyright (c) 2024 Ferenc Géczi <[email protected]>
|
||||
dnl Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
dnl Licensed under the MIT license:
|
||||
dnl
|
||||
dnl Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -82,9 +84,9 @@ dnl
|
||||
dnl If the API changes incompatibly set LIBAGE back to 0
|
||||
dnl
|
||||
|
||||
LIBCURRENT=10 # sync
|
||||
LIBREVISION=0 # with
|
||||
LIBAGE=9 # CMakeLists.txt!
|
||||
LIBCURRENT=11 # sync
|
||||
LIBREVISION=2 # with
|
||||
LIBAGE=10 # CMakeLists.txt!
|
||||
|
||||
AC_CONFIG_HEADERS([expat_config.h])
|
||||
AH_TOP([#ifndef EXPAT_CONFIG_H
|
||||
@@ -160,7 +162,6 @@ AC_C_BIGENDIAN([AC_DEFINE([WORDS_BIGENDIAN], 1)
|
||||
AC_DEFINE_UNQUOTED([BYTEORDER], $BYTEORDER, [1234 = LILENDIAN, 4321 = BIGENDIAN])
|
||||
|
||||
AC_C_CONST
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
AC_ARG_WITH([xmlwf],
|
||||
[AS_HELP_STRING([--without-xmlwf], [do not build xmlwf])],
|
||||
@@ -215,7 +216,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#else
|
||||
# include <stdlib.h> /* for arc4random_buf on BSD */
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
char dummy[[123]]; // double brackets for m4
|
||||
arc4random_buf(dummy, 0U);
|
||||
return 0;
|
||||
@@ -232,7 +233,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
arc4random();
|
||||
return 0;
|
||||
}
|
||||
@@ -254,7 +255,7 @@ AS_IF([test "x$with_getrandom" != xno],
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#include <stdlib.h> /* for NULL */
|
||||
#include <sys/random.h>
|
||||
int main() {
|
||||
int main(void) {
|
||||
return getrandom(NULL, 0U, 0U);
|
||||
}
|
||||
])],
|
||||
@@ -275,10 +276,11 @@ AS_HELP_STRING([--without-sys-getrandom],
|
||||
AS_IF([test "x$with_sys_getrandom" != xno],
|
||||
[AC_MSG_CHECKING([for syscall SYS_getrandom (Linux 3.17+)])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h> /* for NULL */
|
||||
#include <unistd.h> /* for syscall */
|
||||
#include <sys/syscall.h> /* for SYS_getrandom */
|
||||
int main() {
|
||||
int main(void) {
|
||||
syscall(SYS_getrandom, NULL, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
@@ -357,11 +359,22 @@ AS_IF([test "x${DOCBOOK_TO_MAN}" != x -a "x$with_docbook" != xno],
|
||||
page for xmlwf.])])])
|
||||
|
||||
dnl This will make sure that a release tarball shipping a pre-rendered xmlwf man page will
|
||||
dnl get it installed, independent of whether some flavor of docbook2man is available.
|
||||
dnl get it installed, when no working flavor of docbook2man is available (or wanted).
|
||||
dnl This relies on file xmlwf.1 being at least as recent as its source file xmlwf.xml.
|
||||
AS_IF([test -f "${srcdir}"/doc/xmlwf.1],
|
||||
[AM_CONDITIONAL(WITH_DOCBOOK, [true])],
|
||||
[AM_CONDITIONAL(WITH_DOCBOOK, [test "x${DOCBOOK_TO_MAN}" != x])])
|
||||
[AM_CONDITIONAL(WITH_MANPAGE, [true])
|
||||
AS_IF([test "x$with_docbook" = xno -o "x${DOCBOOK_TO_MAN}" = x],
|
||||
[AM_CONDITIONAL(WITH_PREBUILT_MANPAGE, [true])
|
||||
AM_CONDITIONAL(WITH_DISTRIBUTABLE_MANPAGE, [false])],
|
||||
[AM_CONDITIONAL(WITH_PREBUILT_MANPAGE, [false])
|
||||
AM_CONDITIONAL(WITH_DISTRIBUTABLE_MANPAGE, [true])])
|
||||
],
|
||||
[AS_IF([test "x$with_docbook" != xno -a "x${DOCBOOK_TO_MAN}" != x],
|
||||
[AM_CONDITIONAL(WITH_MANPAGE, [true])
|
||||
AM_CONDITIONAL(WITH_DISTRIBUTABLE_MANPAGE, [true])],
|
||||
[AM_CONDITIONAL(WITH_MANPAGE, [false])
|
||||
AM_CONDITIONAL(WITH_DISTRIBUTABLE_MANPAGE, [false])])
|
||||
AM_CONDITIONAL(WITH_PREBUILT_MANPAGE, [false])])
|
||||
|
||||
dnl Configure CMake file templates
|
||||
dnl NOTE: The *_TRUE variables read here are Automake conditionals
|
||||
@@ -392,7 +405,6 @@ LIBDIR_BASENAME="$(basename "${libdir}")"
|
||||
SO_MAJOR="$(expr "${LIBCURRENT}" - "${LIBAGE}")"
|
||||
SO_MINOR="${LIBAGE}"
|
||||
SO_PATCH="${LIBREVISION}"
|
||||
AC_CHECK_SIZEOF([void *]) # sets ac_cv_sizeof_void_p
|
||||
AC_SUBST([EXPAT_ATTR_INFO])
|
||||
AC_SUBST([EXPAT_DTD])
|
||||
AC_SUBST([EXPAT_LARGE_SIZE])
|
||||
@@ -405,8 +417,13 @@ AC_SUBST([LIBDIR_BASENAME])
|
||||
AC_SUBST([SO_MAJOR])
|
||||
AC_SUBST([SO_MINOR])
|
||||
AC_SUBST([SO_PATCH])
|
||||
AC_SUBST([ac_cv_sizeof_void_p])
|
||||
|
||||
dnl The canonical way of doing this is AC_CHECK_SIZEOF(void *), but
|
||||
dnl that adds SIZEOF_VOID_P to expat_config.h.in, making it difficult
|
||||
dnl to have 32-bit and 64-bit versions of libexpat installed on the
|
||||
dnl same system with a single, shared copy of the header.
|
||||
AC_COMPUTE_INT(SIZEOF_VOID_P, [sizeof(void *)])
|
||||
AC_SUBST([SIZEOF_VOID_P])
|
||||
|
||||
dnl write the Automake flags we set
|
||||
AC_SUBST([AM_CPPFLAGS])
|
||||
|
||||
@@ -6,9 +6,10 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017 Stephen Groat <[email protected]>
|
||||
# Copyright (c) 2017 Joe Orton <[email protected]>
|
||||
# Copyright (c) 2024 Tomas Korbar <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -32,26 +33,24 @@
|
||||
|
||||
.PHONY: dist-hook # not inside conditional to avoid automake warning
|
||||
|
||||
if WITH_DOCBOOK
|
||||
if WITH_MANPAGE
|
||||
dist_man_MANS = xmlwf.1
|
||||
|
||||
xmlwf.1: xmlwf.xml
|
||||
-rm -f $@
|
||||
$(DOCBOOK_TO_MAN) $<
|
||||
test "x$(DOCBOOK_TO_MAN)" != x && $(DOCBOOK_TO_MAN) $<
|
||||
test -f $@ || mv XMLWF.1 $@
|
||||
else
|
||||
endif
|
||||
|
||||
if !WITH_DISTRIBUTABLE_MANPAGE
|
||||
dist-hook:
|
||||
@echo 'ERROR: Configure with --with-docbook for "make dist".' 1>&2
|
||||
@false
|
||||
endif
|
||||
|
||||
# https://www.gnu.org/software/automake/manual/automake.html#What-Gets-Cleaned
|
||||
.PHONY: clean-local
|
||||
clean-local: clean-local-check
|
||||
|
||||
.PHONY: clean-local-check
|
||||
clean-local-check:
|
||||
$(RM) xmlwf.1
|
||||
if !WITH_PREBUILT_MANPAGE
|
||||
CLEANFILES = xmlwf.1
|
||||
endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
ok.min.css \
|
||||
|
||||
@@ -22,9 +22,10 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017 Stephen Groat <[email protected]>
|
||||
# Copyright (c) 2017 Joe Orton <[email protected]>
|
||||
# Copyright (c) 2024 Tomas Korbar <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -285,6 +286,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -298,7 +300,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
@@ -345,7 +346,8 @@ target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
@WITH_DOCBOOK_TRUE@dist_man_MANS = xmlwf.1
|
||||
@WITH_MANPAGE_TRUE@dist_man_MANS = xmlwf.1
|
||||
@WITH_PREBUILT_MANPAGE_FALSE@CLEANFILES = xmlwf.1
|
||||
EXTRA_DIST = \
|
||||
ok.min.css \
|
||||
reference.html \
|
||||
@@ -439,7 +441,7 @@ ctags CTAGS:
|
||||
|
||||
cscope cscopelist:
|
||||
|
||||
@WITH_DOCBOOK_TRUE@dist-hook:
|
||||
@WITH_DISTRIBUTABLE_MANPAGE_TRUE@dist-hook:
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
@@ -505,6 +507,7 @@ install-strip:
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
@@ -515,7 +518,7 @@ maintainer-clean-generic:
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-local mostlyclean-am
|
||||
clean-am: clean-generic clean-libtool mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f Makefile
|
||||
@@ -584,38 +587,31 @@ uninstall-man: uninstall-man1
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
|
||||
clean-local cscopelist-am ctags-am dist-hook distclean \
|
||||
distclean-generic distclean-libtool distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-man1 install-pdf \
|
||||
install-pdf-am install-ps install-ps-am install-strip \
|
||||
installcheck installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
|
||||
uninstall-am uninstall-man uninstall-man1
|
||||
cscopelist-am ctags-am dist-hook distclean distclean-generic \
|
||||
distclean-libtool distdir dvi dvi-am html html-am info info-am \
|
||||
install install-am install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-man1 install-pdf install-pdf-am install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
|
||||
ps ps-am tags-am uninstall uninstall-am uninstall-man \
|
||||
uninstall-man1
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
.PHONY: dist-hook # not inside conditional to avoid automake warning
|
||||
|
||||
@WITH_DOCBOOK[email protected]: xmlwf.xml
|
||||
@WITH_DOCBOOK_TRUE@ -rm -f $@
|
||||
@WITH_DOCBOOK_TRUE@ $(DOCBOOK_TO_MAN) $<
|
||||
@WITH_DOCBOOK_TRUE@ test -f $@ || mv XMLWF.1 $@
|
||||
@WITH_DOCBOOK_FALSE@dist-hook:
|
||||
@WITH_DOCBOOK_FALSE@ @echo 'ERROR: Configure with --with-docbook for "make dist".' 1>&2
|
||||
@WITH_DOCBOOK_FALSE@ @false
|
||||
@WITH_MANPAGE[email protected]: xmlwf.xml
|
||||
@WITH_MANPAGE_TRUE@ -rm -f $@
|
||||
@WITH_MANPAGE_TRUE@ test "x$(DOCBOOK_TO_MAN)" != x && $(DOCBOOK_TO_MAN) $<
|
||||
@WITH_MANPAGE_TRUE@ test -f $@ || mv XMLWF.1 $@
|
||||
|
||||
# https://www.gnu.org/software/automake/manual/automake.html#What-Gets-Cleaned
|
||||
.PHONY: clean-local
|
||||
clean-local: clean-local-check
|
||||
|
||||
.PHONY: clean-local-check
|
||||
clean-local-check:
|
||||
$(RM) xmlwf.1
|
||||
@WITH_DISTRIBUTABLE_MANPAGE_FALSE@dist-hook:
|
||||
@WITH_DISTRIBUTABLE_MANPAGE_FALSE@ @echo 'ERROR: Configure with --with-docbook for "make dist".' 1>&2
|
||||
@WITH_DISTRIBUTABLE_MANPAGE_FALSE@ @false
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
Copyright (c) 2000 Clark Cooper <[email protected]>
|
||||
Copyright (c) 2000-2004 Fred L. Drake, Jr. <[email protected]>
|
||||
Copyright (c) 2002-2012 Karl Waclawek <[email protected]>
|
||||
Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
Copyright (c) 2017-2025 Sebastian Pipping <[email protected]>
|
||||
Copyright (c) 2017 Jakub Wilk <[email protected]>
|
||||
Copyright (c) 2021 Tomas Korbar <[email protected]>
|
||||
Copyright (c) 2021 Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
|
||||
@@ -52,7 +52,7 @@
|
||||
<div>
|
||||
<h1>
|
||||
The Expat XML Parser
|
||||
<small>Release 2.6.0</small>
|
||||
<small>Release 2.7.1</small>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
@@ -319,7 +319,7 @@ directions in the next section. Otherwise if you have Microsoft's
|
||||
Developer Studio installed,
|
||||
you can use CMake to generate a <code>.sln</code> file, e.g.
|
||||
<code>
|
||||
cmake -G"Visual Studio 15 2017" -DCMAKE_BUILD_TYPE=RelWithDebInfo .
|
||||
cmake -G"Visual Studio 16 2019" -DCMAKE_BUILD_TYPE=RelWithDebInfo .
|
||||
</code>, and build Expat using <code>msbuild /m expat.sln</code> after.</p>
|
||||
|
||||
<p>Alternatively, you may download the Win32 binary package that
|
||||
@@ -356,10 +356,7 @@ library and header would get installed in
|
||||
<h3>Configuring Expat Using the Pre-Processor</h3>
|
||||
|
||||
<p>Expat's feature set can be configured using a small number of
|
||||
pre-processor definitions. The definition of this symbols does not
|
||||
affect the set of entry points for Expat, only the behavior of the API
|
||||
and the definition of character types in the case of
|
||||
<code>XML_UNICODE_WCHAR_T</code>. The symbols are:</p>
|
||||
pre-processor definitions. The symbols are:</p>
|
||||
|
||||
<dl class="cpp-symbols">
|
||||
<dt><a name="XML_GE">XML_GE</a></dt>
|
||||
@@ -1138,7 +1135,9 @@ containing part (or perhaps all) of the document. The number of bytes of s
|
||||
that are part of the document is indicated by <code>len</code>. This means
|
||||
that <code>s</code> doesn't have to be null-terminated. It also means that
|
||||
if <code>len</code> is larger than the number of bytes in the block of
|
||||
memory that <code>s</code> points at, then a memory fault is likely. The
|
||||
memory that <code>s</code> points at, then a memory fault is likely.
|
||||
Negative values for <code>len</code> are rejected since Expat 2.2.1.
|
||||
The
|
||||
<code>isFinal</code> parameter informs the parser that this is the last
|
||||
piece of the document. Frequently, the last piece is empty (i.e.
|
||||
<code>len</code> is zero.)
|
||||
@@ -1186,11 +1185,17 @@ XML_ParseBuffer(XML_Parser p,
|
||||
int isFinal);
|
||||
</pre>
|
||||
<div class="fcndef">
|
||||
<p>
|
||||
This is just like <code><a href= "#XML_Parse" >XML_Parse</a></code>,
|
||||
except in this case Expat provides the buffer. By obtaining the
|
||||
buffer from Expat with the <code><a href= "#XML_GetBuffer"
|
||||
>XML_GetBuffer</a></code> function, the application can avoid double
|
||||
copying of the input.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Negative values for <code>len</code> are rejected since Expat 2.6.3.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h4 id="XML_GetBuffer">XML_GetBuffer</h4>
|
||||
@@ -1262,6 +1267,11 @@ call-backs, except when parsing an external parameter entity and
|
||||
<code>XML_STATUS_ERROR</code> otherwise. The possible error codes
|
||||
are:</p>
|
||||
<dl>
|
||||
<dt><code>XML_ERROR_NOT_STARTED</code></dt>
|
||||
<dd>
|
||||
when stopping or suspending a parser before it has started,
|
||||
added in Expat 2.6.4.
|
||||
</dd>
|
||||
<dt><code>XML_ERROR_SUSPENDED</code></dt>
|
||||
<dd>when suspending an already suspended parser.</dd>
|
||||
<dt><code>XML_ERROR_FINISHED</code></dt>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
\\$2 \(la\\$1\(ra\\$3
|
||||
..
|
||||
.if \n(.g .mso www.tmac
|
||||
.TH XMLWF 1 "February 6, 2024" "" ""
|
||||
.TH XMLWF 1 "March 27, 2025" "" ""
|
||||
.SH NAME
|
||||
xmlwf \- Determines if an XML document is well-formed
|
||||
.SH SYNOPSIS
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
Copyright (c) 2001 Scott Bronson <[email protected]>
|
||||
Copyright (c) 2002-2003 Fred L. Drake, Jr. <[email protected]>
|
||||
Copyright (c) 2009 Karl Waclawek <[email protected]>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <[email protected]>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <[email protected]>
|
||||
Copyright (c) 2016 Ardo van Rangelrooij <[email protected]>
|
||||
Copyright (c) 2017 Rhodri James <[email protected]>
|
||||
Copyright (c) 2020 Joe Orton <[email protected]>
|
||||
@@ -21,7 +21,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
|
||||
<!ENTITY dhfirstname "<firstname>Scott</firstname>">
|
||||
<!ENTITY dhsurname "<surname>Bronson</surname>">
|
||||
<!ENTITY dhdate "<date>February 6, 2024</date>">
|
||||
<!ENTITY dhdate "<date>March 27, 2025</date>">
|
||||
<!-- Please adjust this^^ date whenever cutting a new release. -->
|
||||
<!ENTITY dhsection "<manvolnum>1</manvolnum>">
|
||||
<!ENTITY dhemail "<email>[email protected]</email>">
|
||||
|
||||
@@ -313,6 +313,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -326,7 +327,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2019 Zhongyuan Zhou <zhouzhongyuan@huawei.com>
|
||||
Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -127,15 +128,15 @@ dumpContentModelElement(const XML_Content *model, unsigned level,
|
||||
}
|
||||
|
||||
// Node
|
||||
printf("[%u] type=%s(%d), quant=%s(%d)", (unsigned)(model - root),
|
||||
contentTypeName(model->type), model->type,
|
||||
contentQuantName(model->quant), model->quant);
|
||||
printf("[%u] type=%s(%u), quant=%s(%u)", (unsigned)(model - root),
|
||||
contentTypeName(model->type), (unsigned int)model->type,
|
||||
contentQuantName(model->quant), (unsigned int)model->quant);
|
||||
if (model->name) {
|
||||
printf(", name=\"%" XML_FMT_STR "\"", model->name);
|
||||
} else {
|
||||
printf(", name=NULL");
|
||||
}
|
||||
printf(", numchildren=%d", model->numchildren);
|
||||
printf(", numchildren=%u", model->numchildren);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,4 @@
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
#undef size_t
|
||||
|
||||
#endif // ndef EXPAT_CONFIG_H
|
||||
@@ -7,6 +7,7 @@
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2019-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -32,10 +33,10 @@ set -e
|
||||
|
||||
filename="${1:-tests/xmltest.log}"
|
||||
|
||||
dos2unix "${filename}"
|
||||
|
||||
tempfile="$(mktemp)"
|
||||
sed \
|
||||
sed -i.bak \
|
||||
-e '# convert DOS line endings to Unix without resorting to dos2unix' \
|
||||
-e $'s/\r//' \
|
||||
\
|
||||
-e 's/^wine: Call .* msvcrt\.dll\._wperror, aborting$/ibm49i02.dtd: No such file or directory/' \
|
||||
\
|
||||
-e '/^wine: /d' \
|
||||
@@ -46,5 +47,4 @@ sed \
|
||||
-e '/^wine client error:/d' \
|
||||
-e '/^In ibm\/invalid\/P49\/: Unhandled exception: unimplemented .\+/d' \
|
||||
\
|
||||
"${filename}" > "${tempfile}"
|
||||
mv "${tempfile}" "${filename}"
|
||||
"${filename}"
|
||||
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
__ __ _
|
||||
___\ \/ /_ __ __ _| |_
|
||||
/ _ \\ /| '_ \ / _` | __|
|
||||
| __// \| |_) | (_| | |_
|
||||
\___/_/\_\ .__/ \__,_|\__|
|
||||
|_| XML parser
|
||||
|
||||
Copyright (c) 2022 Mark Brand <markbrand@google.com>
|
||||
Copyright (c) 2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(NDEBUG)
|
||||
# undef NDEBUG // because checks below rely on assert(...)
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
#include "expat.h"
|
||||
#include "xml_lpm_fuzzer.pb.h"
|
||||
#include "src/libfuzzer/libfuzzer_macro.h"
|
||||
|
||||
static const char *g_encoding = nullptr;
|
||||
static const char *g_external_entity = nullptr;
|
||||
static size_t g_external_entity_size = 0;
|
||||
|
||||
void
|
||||
SetEncoding(const xml_lpm_fuzzer::Encoding &e) {
|
||||
switch (e) {
|
||||
case xml_lpm_fuzzer::Encoding::UTF8:
|
||||
g_encoding = "UTF-8";
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Encoding::UTF16:
|
||||
g_encoding = "UTF-16";
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Encoding::ISO88591:
|
||||
g_encoding = "ISO-8859-1";
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Encoding::ASCII:
|
||||
g_encoding = "US-ASCII";
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Encoding::NONE:
|
||||
g_encoding = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_encoding = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int g_allocation_count = 0;
|
||||
static std::vector<int> g_fail_allocations = {};
|
||||
|
||||
void *
|
||||
MallocHook(size_t size) {
|
||||
g_allocation_count += 1;
|
||||
for (auto index : g_fail_allocations) {
|
||||
if (index == g_allocation_count) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *
|
||||
ReallocHook(void *ptr, size_t size) {
|
||||
g_allocation_count += 1;
|
||||
for (auto index : g_fail_allocations) {
|
||||
if (index == g_allocation_count) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
void
|
||||
FreeHook(void *ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
XML_Memory_Handling_Suite memory_handling_suite
|
||||
= {MallocHook, ReallocHook, FreeHook};
|
||||
|
||||
void InitializeParser(XML_Parser parser);
|
||||
|
||||
// We want a parse function that supports resumption, so that we can cover the
|
||||
// suspend/resume code.
|
||||
enum XML_Status
|
||||
Parse(XML_Parser parser, const char *input, int input_len, int is_final) {
|
||||
enum XML_Status status = XML_Parse(parser, input, input_len, is_final);
|
||||
while (status == XML_STATUS_SUSPENDED) {
|
||||
status = XML_ResumeParser(parser);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// When the fuzzer is compiled with instrumentation such as ASan, then the
|
||||
// accesses in TouchString will fault if they access invalid memory (ie. detect
|
||||
// either a use-after-free or buffer-overflow). By calling TouchString in each
|
||||
// of the callbacks, we can check that the arguments meet the API specifications
|
||||
// in terms of length/null-termination. no_optimize is used to ensure that the
|
||||
// compiler has to emit actual memory reads, instead of removing them.
|
||||
static volatile size_t no_optimize = 0;
|
||||
static void
|
||||
TouchString(const XML_Char *ptr, int len = -1) {
|
||||
if (! ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (len == -1) {
|
||||
for (XML_Char value = *ptr++; value; value = *ptr++) {
|
||||
no_optimize += value;
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; ++i) {
|
||||
no_optimize += ptr[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
TouchNodeAndRecurse(XML_Content *content) {
|
||||
switch (content->type) {
|
||||
case XML_CTYPE_EMPTY:
|
||||
case XML_CTYPE_ANY:
|
||||
assert(content->quant == XML_CQUANT_NONE);
|
||||
assert(content->name == NULL);
|
||||
assert(content->numchildren == 0);
|
||||
assert(content->children == NULL);
|
||||
break;
|
||||
|
||||
case XML_CTYPE_MIXED:
|
||||
assert(content->quant == XML_CQUANT_NONE
|
||||
|| content->quant == XML_CQUANT_REP);
|
||||
assert(content->name == NULL);
|
||||
for (unsigned int i = 0; i < content->numchildren; ++i) {
|
||||
assert(content->children[i].type == XML_CTYPE_NAME);
|
||||
assert(content->children[i].quant == XML_CQUANT_NONE);
|
||||
assert(content->children[i].numchildren == 0);
|
||||
assert(content->children[i].children == NULL);
|
||||
TouchString(content->children[i].name);
|
||||
}
|
||||
break;
|
||||
|
||||
case XML_CTYPE_NAME:
|
||||
assert((content->quant == XML_CQUANT_NONE)
|
||||
|| (content->quant == XML_CQUANT_OPT)
|
||||
|| (content->quant == XML_CQUANT_REP)
|
||||
|| (content->quant == XML_CQUANT_PLUS));
|
||||
assert(content->numchildren == 0);
|
||||
assert(content->children == NULL);
|
||||
TouchString(content->name);
|
||||
break;
|
||||
|
||||
case XML_CTYPE_CHOICE:
|
||||
case XML_CTYPE_SEQ:
|
||||
assert((content->quant == XML_CQUANT_NONE)
|
||||
|| (content->quant == XML_CQUANT_OPT)
|
||||
|| (content->quant == XML_CQUANT_REP)
|
||||
|| (content->quant == XML_CQUANT_PLUS));
|
||||
assert(content->name == NULL);
|
||||
for (unsigned int i = 0; i < content->numchildren; ++i) {
|
||||
TouchNodeAndRecurse(&content->children[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
ElementDeclHandler(void *userData, const XML_Char *name, XML_Content *model) {
|
||||
TouchString(name);
|
||||
TouchNodeAndRecurse(model);
|
||||
XML_FreeContentModel((XML_Parser)userData, model);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
AttlistDeclHandler(void *userData, const XML_Char *elname,
|
||||
const XML_Char *attname, const XML_Char *atttype,
|
||||
const XML_Char *dflt, int isrequired) {
|
||||
(void)userData;
|
||||
TouchString(elname);
|
||||
TouchString(attname);
|
||||
TouchString(atttype);
|
||||
TouchString(dflt);
|
||||
(void)isrequired;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
XmlDeclHandler(void *userData, const XML_Char *version,
|
||||
const XML_Char *encoding, int standalone) {
|
||||
(void)userData;
|
||||
TouchString(version);
|
||||
TouchString(encoding);
|
||||
(void)standalone;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
StartElementHandler(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts) {
|
||||
(void)userData;
|
||||
TouchString(name);
|
||||
for (size_t i = 0; atts[i] != NULL; ++i) {
|
||||
TouchString(atts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
EndElementHandler(void *userData, const XML_Char *name) {
|
||||
(void)userData;
|
||||
TouchString(name);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
CharacterDataHandler(void *userData, const XML_Char *s, int len) {
|
||||
(void)userData;
|
||||
TouchString(s, len);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
ProcessingInstructionHandler(void *userData, const XML_Char *target,
|
||||
const XML_Char *data) {
|
||||
(void)userData;
|
||||
TouchString(target);
|
||||
TouchString(data);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
CommentHandler(void *userData, const XML_Char *data) {
|
||||
TouchString(data);
|
||||
// Use the comment handler to trigger parser suspend, so that we can get
|
||||
// coverage of that code.
|
||||
XML_StopParser((XML_Parser)userData, XML_TRUE);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
StartCdataSectionHandler(void *userData) {
|
||||
(void)userData;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
EndCdataSectionHandler(void *userData) {
|
||||
(void)userData;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
DefaultHandler(void *userData, const XML_Char *s, int len) {
|
||||
(void)userData;
|
||||
TouchString(s, len);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
StartDoctypeDeclHandler(void *userData, const XML_Char *doctypeName,
|
||||
const XML_Char *sysid, const XML_Char *pubid,
|
||||
int has_internal_subset) {
|
||||
(void)userData;
|
||||
TouchString(doctypeName);
|
||||
TouchString(sysid);
|
||||
TouchString(pubid);
|
||||
(void)has_internal_subset;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
EndDoctypeDeclHandler(void *userData) {
|
||||
(void)userData;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
EntityDeclHandler(void *userData, const XML_Char *entityName,
|
||||
int is_parameter_entity, const XML_Char *value,
|
||||
int value_length, const XML_Char *base,
|
||||
const XML_Char *systemId, const XML_Char *publicId,
|
||||
const XML_Char *notationName) {
|
||||
(void)userData;
|
||||
TouchString(entityName);
|
||||
(void)is_parameter_entity;
|
||||
TouchString(value, value_length);
|
||||
TouchString(base);
|
||||
TouchString(systemId);
|
||||
TouchString(publicId);
|
||||
TouchString(notationName);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
NotationDeclHandler(void *userData, const XML_Char *notationName,
|
||||
const XML_Char *base, const XML_Char *systemId,
|
||||
const XML_Char *publicId) {
|
||||
(void)userData;
|
||||
TouchString(notationName);
|
||||
TouchString(base);
|
||||
TouchString(systemId);
|
||||
TouchString(publicId);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
StartNamespaceDeclHandler(void *userData, const XML_Char *prefix,
|
||||
const XML_Char *uri) {
|
||||
(void)userData;
|
||||
TouchString(prefix);
|
||||
TouchString(uri);
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
EndNamespaceDeclHandler(void *userData, const XML_Char *prefix) {
|
||||
(void)userData;
|
||||
TouchString(prefix);
|
||||
}
|
||||
|
||||
static int XMLCALL
|
||||
NotStandaloneHandler(void *userData) {
|
||||
(void)userData;
|
||||
return XML_STATUS_OK;
|
||||
}
|
||||
|
||||
static int XMLCALL
|
||||
ExternalEntityRefHandler(XML_Parser parser, const XML_Char *context,
|
||||
const XML_Char *base, const XML_Char *systemId,
|
||||
const XML_Char *publicId) {
|
||||
int rc = XML_STATUS_ERROR;
|
||||
TouchString(context);
|
||||
TouchString(base);
|
||||
TouchString(systemId);
|
||||
TouchString(publicId);
|
||||
|
||||
if (g_external_entity) {
|
||||
XML_Parser ext_parser
|
||||
= XML_ExternalEntityParserCreate(parser, context, g_encoding);
|
||||
rc = Parse(ext_parser, g_external_entity, g_external_entity_size, 1);
|
||||
XML_ParserFree(ext_parser);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
SkippedEntityHandler(void *userData, const XML_Char *entityName,
|
||||
int is_parameter_entity) {
|
||||
(void)userData;
|
||||
TouchString(entityName);
|
||||
(void)is_parameter_entity;
|
||||
}
|
||||
|
||||
static int XMLCALL
|
||||
UnknownEncodingHandler(void *encodingHandlerData, const XML_Char *name,
|
||||
XML_Encoding *info) {
|
||||
(void)encodingHandlerData;
|
||||
TouchString(name);
|
||||
(void)info;
|
||||
return XML_STATUS_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
InitializeParser(XML_Parser parser) {
|
||||
XML_SetUserData(parser, (void *)parser);
|
||||
XML_SetHashSalt(parser, 0x41414141);
|
||||
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
|
||||
XML_SetElementDeclHandler(parser, ElementDeclHandler);
|
||||
XML_SetAttlistDeclHandler(parser, AttlistDeclHandler);
|
||||
XML_SetXmlDeclHandler(parser, XmlDeclHandler);
|
||||
XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
|
||||
XML_SetCharacterDataHandler(parser, CharacterDataHandler);
|
||||
XML_SetProcessingInstructionHandler(parser, ProcessingInstructionHandler);
|
||||
XML_SetCommentHandler(parser, CommentHandler);
|
||||
XML_SetCdataSectionHandler(parser, StartCdataSectionHandler,
|
||||
EndCdataSectionHandler);
|
||||
// XML_SetDefaultHandler disables entity expansion
|
||||
XML_SetDefaultHandlerExpand(parser, DefaultHandler);
|
||||
XML_SetDoctypeDeclHandler(parser, StartDoctypeDeclHandler,
|
||||
EndDoctypeDeclHandler);
|
||||
// Note: This is mutually exclusive with XML_SetUnparsedEntityDeclHandler,
|
||||
// and there isn't any significant code change between the two.
|
||||
XML_SetEntityDeclHandler(parser, EntityDeclHandler);
|
||||
XML_SetNotationDeclHandler(parser, NotationDeclHandler);
|
||||
XML_SetNamespaceDeclHandler(parser, StartNamespaceDeclHandler,
|
||||
EndNamespaceDeclHandler);
|
||||
XML_SetNotStandaloneHandler(parser, NotStandaloneHandler);
|
||||
XML_SetExternalEntityRefHandler(parser, ExternalEntityRefHandler);
|
||||
XML_SetSkippedEntityHandler(parser, SkippedEntityHandler);
|
||||
XML_SetUnknownEncodingHandler(parser, UnknownEncodingHandler, (void *)parser);
|
||||
}
|
||||
|
||||
DEFINE_TEXT_PROTO_FUZZER(const xml_lpm_fuzzer::Testcase &testcase) {
|
||||
g_external_entity = nullptr;
|
||||
|
||||
if (! testcase.actions_size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_allocation_count = 0;
|
||||
g_fail_allocations.clear();
|
||||
for (int i = 0; i < testcase.fail_allocations_size(); ++i) {
|
||||
g_fail_allocations.push_back(testcase.fail_allocations(i));
|
||||
}
|
||||
|
||||
SetEncoding(testcase.encoding());
|
||||
XML_Parser parser
|
||||
= XML_ParserCreate_MM(g_encoding, &memory_handling_suite, "|");
|
||||
InitializeParser(parser);
|
||||
|
||||
for (int i = 0; i < testcase.actions_size(); ++i) {
|
||||
const auto &action = testcase.actions(i);
|
||||
switch (action.action_case()) {
|
||||
case xml_lpm_fuzzer::Action::kChunk:
|
||||
if (XML_STATUS_ERROR
|
||||
== Parse(parser, action.chunk().data(), action.chunk().size(), 0)) {
|
||||
// Force a reset after parse error.
|
||||
XML_ParserReset(parser, g_encoding);
|
||||
InitializeParser(parser);
|
||||
}
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Action::kLastChunk:
|
||||
Parse(parser, action.last_chunk().data(), action.last_chunk().size(), 1);
|
||||
XML_ParserReset(parser, g_encoding);
|
||||
InitializeParser(parser);
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Action::kReset:
|
||||
XML_ParserReset(parser, g_encoding);
|
||||
InitializeParser(parser);
|
||||
break;
|
||||
|
||||
case xml_lpm_fuzzer::Action::kExternalEntity:
|
||||
g_external_entity = action.external_entity().data();
|
||||
g_external_entity_size = action.external_entity().size();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
__ __ _
|
||||
___\ \/ /_ __ __ _| |_
|
||||
/ _ \\ /| '_ \ / _` | __|
|
||||
| __// \| |_) | (_| | |_
|
||||
\___/_/\_\ .__/ \__,_|\__|
|
||||
|_| XML parser
|
||||
|
||||
Copyright (c) 2022 Mark Brand <[email protected]>
|
||||
Copyright (c) 2025 Sebastian Pipping <[email protected]>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
syntax = "proto2";
|
||||
package xml_lpm_fuzzer;
|
||||
|
||||
enum Encoding {
|
||||
UTF8 = 0;
|
||||
UTF16 = 1;
|
||||
ISO88591 = 2;
|
||||
ASCII = 3;
|
||||
UNKNOWN = 4;
|
||||
NONE = 5;
|
||||
}
|
||||
|
||||
message Action {
|
||||
oneof action {
|
||||
string chunk = 1;
|
||||
string last_chunk = 2;
|
||||
bool reset = 3;
|
||||
string external_entity = 4;
|
||||
}
|
||||
}
|
||||
|
||||
message Testcase {
|
||||
required Encoding encoding = 1;
|
||||
repeated Action actions = 2;
|
||||
repeated int32 fail_allocations = 3;
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://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,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* https://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,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017 Tomasz Kłoczko <[email protected]>
|
||||
# Copyright (c) 2019 David Loffredo <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
@@ -36,7 +36,9 @@ include_HEADERS = \
|
||||
expat_external.h
|
||||
|
||||
lib_LTLIBRARIES = libexpat.la
|
||||
noinst_LTLIBRARIES = libexpatinternal.la
|
||||
if WITH_TESTS
|
||||
noinst_LTLIBRARIES = libtestpat.la
|
||||
endif
|
||||
|
||||
libexpat_la_LDFLAGS = \
|
||||
@AM_LDFLAGS@ \
|
||||
@@ -44,17 +46,16 @@ libexpat_la_LDFLAGS = \
|
||||
-no-undefined \
|
||||
-version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@
|
||||
|
||||
libexpat_la_SOURCES =
|
||||
|
||||
# This layer of indirection allows
|
||||
# the test suite to access internal symbols
|
||||
# despite compiling with -fvisibility=hidden
|
||||
libexpatinternal_la_SOURCES = \
|
||||
libexpat_la_SOURCES = \
|
||||
xmlparse.c \
|
||||
xmltok.c \
|
||||
xmlrole.c
|
||||
|
||||
libexpat_la_LIBADD = libexpatinternal.la
|
||||
if WITH_TESTS
|
||||
libtestpat_la_CPPFLAGS = -DXML_TESTING
|
||||
|
||||
libtestpat_la_SOURCES = $(libexpat_la_SOURCES)
|
||||
endif
|
||||
|
||||
doc_DATA = \
|
||||
../AUTHORS \
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2022 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017 Tomasz Kłoczko <[email protected]>
|
||||
# Copyright (c) 2019 David Loffredo <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
@@ -176,8 +176,8 @@ am__uninstall_files_from_dir = { \
|
||||
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(docdir)" \
|
||||
"$(DESTDIR)$(includedir)"
|
||||
LTLIBRARIES = $(lib_LTLIBRARIES) $(noinst_LTLIBRARIES)
|
||||
libexpat_la_DEPENDENCIES = libexpatinternal.la
|
||||
am_libexpat_la_OBJECTS =
|
||||
libexpat_la_LIBADD =
|
||||
am_libexpat_la_OBJECTS = xmlparse.lo xmltok.lo xmlrole.lo
|
||||
libexpat_la_OBJECTS = $(am_libexpat_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
@@ -186,9 +186,13 @@ am__v_lt_1 =
|
||||
libexpat_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
|
||||
$(libexpat_la_LDFLAGS) $(LDFLAGS) -o $@
|
||||
libexpatinternal_la_LIBADD =
|
||||
am_libexpatinternal_la_OBJECTS = xmlparse.lo xmltok.lo xmlrole.lo
|
||||
libexpatinternal_la_OBJECTS = $(am_libexpatinternal_la_OBJECTS)
|
||||
libtestpat_la_LIBADD =
|
||||
am__libtestpat_la_SOURCES_DIST = xmlparse.c xmltok.c xmlrole.c
|
||||
am__objects_1 = libtestpat_la-xmlparse.lo libtestpat_la-xmltok.lo \
|
||||
libtestpat_la-xmlrole.lo
|
||||
@WITH_TESTS_TRUE@am_libtestpat_la_OBJECTS = $(am__objects_1)
|
||||
libtestpat_la_OBJECTS = $(am_libtestpat_la_OBJECTS)
|
||||
@WITH_TESTS_TRUE@am_libtestpat_la_rpath =
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
@@ -204,8 +208,10 @@ am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/conftools/depcomp
|
||||
am__maybe_remake_depfiles = depfiles
|
||||
am__depfiles_remade = ./$(DEPDIR)/xmlparse.Plo ./$(DEPDIR)/xmlrole.Plo \
|
||||
./$(DEPDIR)/xmltok.Plo
|
||||
am__depfiles_remade = ./$(DEPDIR)/libtestpat_la-xmlparse.Plo \
|
||||
./$(DEPDIR)/libtestpat_la-xmlrole.Plo \
|
||||
./$(DEPDIR)/libtestpat_la-xmltok.Plo ./$(DEPDIR)/xmlparse.Plo \
|
||||
./$(DEPDIR)/xmlrole.Plo ./$(DEPDIR)/xmltok.Plo
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
@@ -225,8 +231,9 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(libexpat_la_SOURCES) $(libexpatinternal_la_SOURCES)
|
||||
DIST_SOURCES = $(libexpat_la_SOURCES) $(libexpatinternal_la_SOURCES)
|
||||
SOURCES = $(libexpat_la_SOURCES) $(libtestpat_la_SOURCES)
|
||||
DIST_SOURCES = $(libexpat_la_SOURCES) \
|
||||
$(am__libtestpat_la_SOURCES_DIST)
|
||||
am__can_run_installinfo = \
|
||||
case $$AM_UPDATE_INFO_DIR in \
|
||||
n|no|NO) false;; \
|
||||
@@ -344,6 +351,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -357,7 +365,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
@@ -410,24 +417,20 @@ include_HEADERS = \
|
||||
expat_external.h
|
||||
|
||||
lib_LTLIBRARIES = libexpat.la
|
||||
noinst_LTLIBRARIES = libexpatinternal.la
|
||||
@WITH_TESTS_TRUE@noinst_LTLIBRARIES = libtestpat.la
|
||||
libexpat_la_LDFLAGS = \
|
||||
@AM_LDFLAGS@ \
|
||||
@LIBM@ \
|
||||
-no-undefined \
|
||||
-version-info @LIBCURRENT@:@LIBREVISION@:@LIBAGE@
|
||||
|
||||
libexpat_la_SOURCES =
|
||||
|
||||
# This layer of indirection allows
|
||||
# the test suite to access internal symbols
|
||||
# despite compiling with -fvisibility=hidden
|
||||
libexpatinternal_la_SOURCES = \
|
||||
libexpat_la_SOURCES = \
|
||||
xmlparse.c \
|
||||
xmltok.c \
|
||||
xmlrole.c
|
||||
|
||||
libexpat_la_LIBADD = libexpatinternal.la
|
||||
@WITH_TESTS_TRUE@libtestpat_la_CPPFLAGS = -DXML_TESTING
|
||||
@WITH_TESTS_TRUE@libtestpat_la_SOURCES = $(libexpat_la_SOURCES)
|
||||
doc_DATA = \
|
||||
../AUTHORS \
|
||||
../Changes
|
||||
@@ -534,8 +537,8 @@ clean-noinstLTLIBRARIES:
|
||||
libexpat.la: $(libexpat_la_OBJECTS) $(libexpat_la_DEPENDENCIES) $(EXTRA_libexpat_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(libexpat_la_LINK) -rpath $(libdir) $(libexpat_la_OBJECTS) $(libexpat_la_LIBADD) $(LIBS)
|
||||
|
||||
libexpatinternal.la: $(libexpatinternal_la_OBJECTS) $(libexpatinternal_la_DEPENDENCIES) $(EXTRA_libexpatinternal_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(libexpatinternal_la_OBJECTS) $(libexpatinternal_la_LIBADD) $(LIBS)
|
||||
libtestpat.la: $(libtestpat_la_OBJECTS) $(libtestpat_la_DEPENDENCIES) $(EXTRA_libtestpat_la_DEPENDENCIES)
|
||||
$(AM_V_CCLD)$(LINK) $(am_libtestpat_la_rpath) $(libtestpat_la_OBJECTS) $(libtestpat_la_LIBADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
@@ -543,6 +546,9 @@ mostlyclean-compile:
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmlparse.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmlrole.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtestpat_la-xmltok.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlparse.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmlrole.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmltok.Plo@am__quote@ # am--include-marker
|
||||
@@ -574,6 +580,27 @@ am--depfiles: $(am__depfiles_remade)
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
libtestpat_la-xmlparse.lo: xmlparse.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtestpat_la-xmlparse.lo -MD -MP -MF $(DEPDIR)/libtestpat_la-xmlparse.Tpo -c -o libtestpat_la-xmlparse.lo `test -f 'xmlparse.c' || echo '$(srcdir)/'`xmlparse.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestpat_la-xmlparse.Tpo $(DEPDIR)/libtestpat_la-xmlparse.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xmlparse.c' object='libtestpat_la-xmlparse.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtestpat_la-xmlparse.lo `test -f 'xmlparse.c' || echo '$(srcdir)/'`xmlparse.c
|
||||
|
||||
libtestpat_la-xmltok.lo: xmltok.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtestpat_la-xmltok.lo -MD -MP -MF $(DEPDIR)/libtestpat_la-xmltok.Tpo -c -o libtestpat_la-xmltok.lo `test -f 'xmltok.c' || echo '$(srcdir)/'`xmltok.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestpat_la-xmltok.Tpo $(DEPDIR)/libtestpat_la-xmltok.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xmltok.c' object='libtestpat_la-xmltok.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtestpat_la-xmltok.lo `test -f 'xmltok.c' || echo '$(srcdir)/'`xmltok.c
|
||||
|
||||
libtestpat_la-xmlrole.lo: xmlrole.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libtestpat_la-xmlrole.lo -MD -MP -MF $(DEPDIR)/libtestpat_la-xmlrole.Tpo -c -o libtestpat_la-xmlrole.lo `test -f 'xmlrole.c' || echo '$(srcdir)/'`xmlrole.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtestpat_la-xmlrole.Tpo $(DEPDIR)/libtestpat_la-xmlrole.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xmlrole.c' object='libtestpat_la-xmlrole.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libtestpat_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libtestpat_la-xmlrole.lo `test -f 'xmlrole.c' || echo '$(srcdir)/'`xmlrole.c
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
@@ -749,7 +776,10 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
|
||||
clean-noinstLTLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -f ./$(DEPDIR)/xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo
|
||||
-rm -f ./$(DEPDIR)/xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/xmlrole.Plo
|
||||
-rm -f ./$(DEPDIR)/xmltok.Plo
|
||||
-rm -f Makefile
|
||||
@@ -798,7 +828,10 @@ install-ps-am:
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -f ./$(DEPDIR)/xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmlrole.Plo
|
||||
-rm -f ./$(DEPDIR)/libtestpat_la-xmltok.Plo
|
||||
-rm -f ./$(DEPDIR)/xmlparse.Plo
|
||||
-rm -f ./$(DEPDIR)/xmlrole.Plo
|
||||
-rm -f ./$(DEPDIR)/xmltok.Plo
|
||||
-rm -f Makefile
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
Copyright (c) 2000-2005 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2001-2002 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2002-2016 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016 Cristian Rodríguez <crrodriguez@opensuse.org>
|
||||
Copyright (c) 2016 Thomas Beutlich <tc@tbeu.de>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2022 Thijs Schreijer <thijs@thijsschreijer.nl>
|
||||
Copyright (c) 2023 Hanno Böck <hanno@gentoo.org>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -129,7 +130,9 @@ enum XML_Error {
|
||||
/* Added in 2.3.0. */
|
||||
XML_ERROR_NO_BUFFER,
|
||||
/* Added in 2.4.0. */
|
||||
XML_ERROR_AMPLIFICATION_LIMIT_BREACH
|
||||
XML_ERROR_AMPLIFICATION_LIMIT_BREACH,
|
||||
/* Added in 2.6.4. */
|
||||
XML_ERROR_NOT_STARTED,
|
||||
};
|
||||
|
||||
enum XML_Content_Type {
|
||||
@@ -1042,7 +1045,7 @@ typedef struct {
|
||||
XMLPARSEAPI(const XML_Feature *)
|
||||
XML_GetFeatureList(void);
|
||||
|
||||
#if XML_GE == 1
|
||||
#if defined(XML_DTD) || (defined(XML_GE) && XML_GE == 1)
|
||||
/* Added in Expat 2.4.0 for XML_DTD defined and
|
||||
* added in Expat 2.6.0 for XML_GE == 1. */
|
||||
XMLPARSEAPI(XML_Bool)
|
||||
@@ -1064,8 +1067,8 @@ XML_SetReparseDeferralEnabled(XML_Parser parser, XML_Bool enabled);
|
||||
See https://semver.org
|
||||
*/
|
||||
#define XML_MAJOR_VERSION 2
|
||||
#define XML_MINOR_VERSION 6
|
||||
#define XML_MICRO_VERSION 0
|
||||
#define XML_MINOR_VERSION 7
|
||||
#define XML_MICRO_VERSION 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
Copyright (c) 2002-2003 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2002-2006 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2018 Yury Gribov <tetra2005@gmail.com>
|
||||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2024 Taichi Haradaguchi <20001722@ymail.ne.jp>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -126,6 +127,9 @@
|
||||
# elif ULONG_MAX == 18446744073709551615u // 2^64-1
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "lu"
|
||||
# elif defined(EMSCRIPTEN) // 32bit mode Emscripten
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "ld"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "zu"
|
||||
# else
|
||||
# define EXPAT_FMT_PTRDIFF_T(midpart) "%" midpart "d"
|
||||
# define EXPAT_FMT_SIZE_T(midpart) "%" midpart "u"
|
||||
@@ -155,14 +159,20 @@ extern "C" {
|
||||
void _INTERNAL_trim_to_complete_utf8_characters(const char *from,
|
||||
const char **fromLimRef);
|
||||
|
||||
#if XML_GE == 1
|
||||
#if defined(XML_GE) && XML_GE == 1
|
||||
unsigned long long testingAccountingGetCountBytesDirect(XML_Parser parser);
|
||||
unsigned long long testingAccountingGetCountBytesIndirect(XML_Parser parser);
|
||||
const char *unsignedCharToPrintable(unsigned char c);
|
||||
#endif
|
||||
|
||||
extern XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c
|
||||
extern unsigned int g_parseAttempts; // used for testing only
|
||||
extern
|
||||
#if ! defined(XML_TESTING)
|
||||
const
|
||||
#endif
|
||||
XML_Bool g_reparseDeferralEnabledDefault; // written ONLY in runtests.c
|
||||
#if defined(XML_TESTING)
|
||||
extern unsigned int g_bytesScanned; // used for testing only
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -126,8 +126,7 @@
|
||||
| ((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) \
|
||||
| ((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
|
||||
|
||||
#define SIPHASH_INITIALIZER \
|
||||
{ 0, 0, 0, 0, {0}, 0, 0 }
|
||||
#define SIPHASH_INITIALIZER {0, 0, 0, 0, {0}, 0, 0}
|
||||
|
||||
struct siphash {
|
||||
uint64_t v0, v1, v2, v3;
|
||||
|
||||
+487
-174
File diff suppressed because it is too large.
Load diff
@@ -6,9 +6,10 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2023 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
||||
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
SUBDIRS = . benchmark
|
||||
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib -DXML_TESTING
|
||||
|
||||
check_PROGRAMS = runtests runtests_cxx
|
||||
TESTS = runtests runtests_cxx
|
||||
@@ -72,8 +73,8 @@ runtests_cxx_SOURCES = \
|
||||
runtests_cxx.cpp \
|
||||
structdata_cxx.cpp
|
||||
|
||||
runtests_LDADD = ../lib/libexpatinternal.la
|
||||
runtests_cxx_LDADD = ../lib/libexpatinternal.la
|
||||
runtests_LDADD = ../lib/libtestpat.la
|
||||
runtests_cxx_LDADD = ../lib/libtestpat.la
|
||||
|
||||
runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
||||
runtests_cxx_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
||||
@@ -92,7 +93,7 @@ EXTRA_DIST = \
|
||||
structdata.h \
|
||||
minicheck.h \
|
||||
memcheck.h \
|
||||
README.txt \
|
||||
README.md \
|
||||
udiffer.py \
|
||||
xmltest.log.expected \
|
||||
xmltest.sh
|
||||
@@ -22,9 +22,10 @@
|
||||
# \___/_/\_\ .__/ \__,_|\__|
|
||||
# |_| XML parser
|
||||
#
|
||||
# Copyright (c) 2017-2023 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2024 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017-2022 Rhodri James <[email protected]>
|
||||
# Copyright (c) 2020 Jeffrey Walton <[email protected]>
|
||||
# Copyright (c) 2024 Dag-Erling Smørgrav <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -151,7 +152,7 @@ am_runtests_OBJECTS = acc_tests.$(OBJEXT) alloc_tests.$(OBJEXT) \
|
||||
nsalloc_tests.$(OBJEXT) runtests.$(OBJEXT) \
|
||||
structdata.$(OBJEXT)
|
||||
runtests_OBJECTS = $(am_runtests_OBJECTS)
|
||||
runtests_DEPENDENCIES = ../lib/libexpatinternal.la
|
||||
runtests_DEPENDENCIES = ../lib/libtestpat.la
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
am__v_lt_0 = --silent
|
||||
@@ -168,7 +169,7 @@ am_runtests_cxx_OBJECTS = acc_tests_cxx.$(OBJEXT) \
|
||||
ns_tests_cxx.$(OBJEXT) runtests_cxx.$(OBJEXT) \
|
||||
structdata_cxx.$(OBJEXT)
|
||||
runtests_cxx_OBJECTS = $(am_runtests_cxx_OBJECTS)
|
||||
runtests_cxx_DEPENDENCIES = ../lib/libexpatinternal.la
|
||||
runtests_cxx_DEPENDENCIES = ../lib/libtestpat.la
|
||||
runtests_cxx_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
|
||||
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
|
||||
$(CXXFLAGS) $(runtests_cxx_LDFLAGS) $(LDFLAGS) -o $@
|
||||
@@ -485,7 +486,7 @@ TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in \
|
||||
$(top_srcdir)/conftools/depcomp \
|
||||
$(top_srcdir)/conftools/test-driver
|
||||
$(top_srcdir)/conftools/test-driver README.md
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
am__relativize = \
|
||||
dir0=`pwd`; \
|
||||
@@ -515,7 +516,7 @@ am__relativize = \
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_CFLAGS = @AM_CFLAGS@
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(srcdir)/../lib -DXML_TESTING
|
||||
AM_CXXFLAGS = @AM_CXXFLAGS@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
AM_LDFLAGS = @AM_LDFLAGS@
|
||||
@@ -602,6 +603,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -615,7 +617,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
@@ -698,8 +699,8 @@ runtests_cxx_SOURCES = \
|
||||
runtests_cxx.cpp \
|
||||
structdata_cxx.cpp
|
||||
|
||||
runtests_LDADD = ../lib/libexpatinternal.la
|
||||
runtests_cxx_LDADD = ../lib/libexpatinternal.la
|
||||
runtests_LDADD = ../lib/libtestpat.la
|
||||
runtests_cxx_LDADD = ../lib/libtestpat.la
|
||||
runtests_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
||||
runtests_cxx_LDFLAGS = @AM_LDFLAGS@ @LIBM@
|
||||
EXTRA_DIST = \
|
||||
@@ -716,7 +717,7 @@ EXTRA_DIST = \
|
||||
structdata.h \
|
||||
minicheck.h \
|
||||
memcheck.h \
|
||||
README.txt \
|
||||
README.md \
|
||||
udiffer.py \
|
||||
xmltest.log.expected \
|
||||
xmltest.sh
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
This directory contains the test suite for Expat. The tests provide
|
||||
general unit testing and regression coverage. The tests are not
|
||||
expected to be useful examples of Expat usage; see the
|
||||
[examples](../examples) directory for that.
|
||||
|
||||
The Expat tests use a partial internal implementation of the
|
||||
[Check](https://libcheck.github.io/check/) unit testing framework for
|
||||
C.
|
||||
|
||||
Expat must be built and, on some platforms, installed, before the
|
||||
tests can be run.
|
||||
@@ -1,13 +0,0 @@
|
||||
This directory contains the (fledgling) test suite for Expat. The
|
||||
tests provide general unit testing and regression coverage. The tests
|
||||
are not expected to be useful examples of Expat usage; see the
|
||||
examples/ directory for that.
|
||||
|
||||
The Expat tests use a partial internal implementation of the "Check"
|
||||
unit testing framework for C. More information on Check can be found at:
|
||||
|
||||
http://check.sourceforge.net/
|
||||
|
||||
Expat must be built and, depending on platform, must be installed, before "make check" can be executed.
|
||||
|
||||
This test suite can all change in a later version.
|
||||
@@ -360,13 +360,16 @@ END_TEST
|
||||
START_TEST(test_helper_unsigned_char_to_printable) {
|
||||
// Smoke test
|
||||
unsigned char uc = 0;
|
||||
for (; uc < (unsigned char)-1; uc++) {
|
||||
for (;; uc++) {
|
||||
set_subtest("char %u", (unsigned)uc);
|
||||
const char *const printable = unsignedCharToPrintable(uc);
|
||||
if (printable == NULL)
|
||||
fail("unsignedCharToPrintable returned NULL");
|
||||
else if (strlen(printable) < (size_t)1)
|
||||
fail("unsignedCharToPrintable returned empty string");
|
||||
if (uc == (unsigned char)-1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Two concrete samples
|
||||
@@ -378,6 +381,63 @@ START_TEST(test_helper_unsigned_char_to_printable) {
|
||||
fail("unsignedCharToPrintable result mistaken");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_amplification_isolated_external_parser) {
|
||||
// NOTE: Length 44 is precisely twice the length of "<!ENTITY a SYSTEM 'b'>"
|
||||
// (22) that is used in function accountingGetCurrentAmplification in
|
||||
// xmlparse.c.
|
||||
// 1.........1.........1.........1.........1..4 => 44
|
||||
const char doc[] = "<!ENTITY % p1 '123456789_123456789_1234567'>";
|
||||
const int docLen = (int)sizeof(doc) - 1;
|
||||
const float maximumToleratedAmplification = 2.0f;
|
||||
|
||||
struct TestCase {
|
||||
int offsetOfThreshold;
|
||||
enum XML_Status expectedStatus;
|
||||
};
|
||||
|
||||
struct TestCase cases[] = {
|
||||
{-2, XML_STATUS_ERROR}, {-1, XML_STATUS_ERROR}, {0, XML_STATUS_ERROR},
|
||||
{+1, XML_STATUS_OK}, {+2, XML_STATUS_OK},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
const int offsetOfThreshold = cases[i].offsetOfThreshold;
|
||||
const enum XML_Status expectedStatus = cases[i].expectedStatus;
|
||||
const unsigned long long activationThresholdBytes
|
||||
= docLen + offsetOfThreshold;
|
||||
|
||||
set_subtest("offsetOfThreshold=%d, expectedStatus=%d", offsetOfThreshold,
|
||||
expectedStatus);
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
|
||||
assert_true(XML_SetBillionLaughsAttackProtectionMaximumAmplification(
|
||||
parser, maximumToleratedAmplification)
|
||||
== XML_TRUE);
|
||||
assert_true(XML_SetBillionLaughsAttackProtectionActivationThreshold(
|
||||
parser, activationThresholdBytes)
|
||||
== XML_TRUE);
|
||||
|
||||
XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, NULL, NULL);
|
||||
assert_true(ext_parser != NULL);
|
||||
|
||||
const enum XML_Status actualStatus
|
||||
= _XML_Parse_SINGLE_BYTES(ext_parser, doc, docLen, XML_TRUE);
|
||||
|
||||
assert_true(actualStatus == expectedStatus);
|
||||
if (actualStatus != XML_STATUS_OK) {
|
||||
assert_true(XML_GetErrorCode(ext_parser)
|
||||
== XML_ERROR_AMPLIFICATION_LIMIT_BREACH);
|
||||
}
|
||||
|
||||
XML_ParserFree(ext_parser);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
#endif // XML_GE == 1
|
||||
|
||||
void
|
||||
@@ -390,6 +450,8 @@ make_accounting_test_case(Suite *s) {
|
||||
tcase_add_test(tc_accounting, test_accounting_precision);
|
||||
tcase_add_test(tc_accounting, test_billion_laughs_attack_protection_api);
|
||||
tcase_add_test(tc_accounting, test_helper_unsigned_char_to_printable);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_accounting,
|
||||
test_amplification_isolated_external_parser);
|
||||
#else
|
||||
UNUSED_P(s);
|
||||
#endif /* XML_GE == 1 */
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
|
||||
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
|
||||
Copyright (c) 2023 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -450,6 +451,31 @@ START_TEST(test_alloc_internal_entity) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_alloc_parameter_entity) {
|
||||
const char *text = "<!DOCTYPE foo ["
|
||||
"<!ENTITY % param1 \"<!ENTITY internal 'some_text'>\">"
|
||||
"%param1;"
|
||||
"]> <foo>&internal;content</foo>";
|
||||
int i;
|
||||
const int alloc_test_max_repeats = 30;
|
||||
|
||||
for (i = 0; i < alloc_test_max_repeats; i++) {
|
||||
g_allocation_count = i;
|
||||
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
!= XML_STATUS_ERROR)
|
||||
break;
|
||||
alloc_teardown();
|
||||
alloc_setup();
|
||||
}
|
||||
g_allocation_count = -1;
|
||||
if (i == 0)
|
||||
fail("Parameter entity processed despite duff allocator");
|
||||
if (i == alloc_test_max_repeats)
|
||||
fail("Parameter entity not processed at max allocation count");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test the robustness against allocation failure of element handling
|
||||
* Based on test_dtd_default_handling().
|
||||
*/
|
||||
@@ -2079,6 +2105,7 @@ make_alloc_test_case(Suite *s) {
|
||||
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_external_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_ext_entity_set_encoding);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_internal_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_parameter_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_alloc, test_alloc_dtd_default_handling);
|
||||
tcase_add_test(tc_alloc, test_alloc_explicit_encoding);
|
||||
tcase_add_test(tc_alloc, test_alloc_set_base);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
|
||||
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
|
||||
@@ -19,6 +19,7 @@
|
||||
Copyright (c) 2020 Tim Gates <tim.gates@iress.com>
|
||||
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
|
||||
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Copyright (c) 2024-2025 Berkay Eren Ürün <berkay.ueruen@siemens.com>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -1191,6 +1192,22 @@ START_TEST(test_not_standalone_handler_accept) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_entity_start_tag_level_greater_than_one) {
|
||||
const char *const text = "<!DOCTYPE t1 [\n"
|
||||
" <!ENTITY e1 'hello'>\n"
|
||||
"]>\n"
|
||||
"<t1>\n"
|
||||
" <t2>&e1;</t2>\n"
|
||||
"</t1>\n";
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text),
|
||||
/*isFinal*/ XML_TRUE)
|
||||
== XML_STATUS_OK);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_wfc_no_recursive_entity_refs) {
|
||||
const char *text = "<!DOCTYPE doc [\n"
|
||||
" <!ENTITY entity '&entity;'>\n"
|
||||
@@ -1202,6 +1219,136 @@ START_TEST(test_wfc_no_recursive_entity_refs) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_no_indirectly_recursive_entity_refs) {
|
||||
struct TestCase {
|
||||
const char *doc;
|
||||
bool usesParameterEntities;
|
||||
};
|
||||
|
||||
const struct TestCase cases[] = {
|
||||
// general entity + character data
|
||||
{"<!DOCTYPE a [\n"
|
||||
" <!ENTITY e1 '&e2;'>\n"
|
||||
" <!ENTITY e2 '&e1;'>\n"
|
||||
"]><a>&e2;</a>\n",
|
||||
false},
|
||||
|
||||
// general entity + attribute value
|
||||
{"<!DOCTYPE a [\n"
|
||||
" <!ENTITY e1 '&e2;'>\n"
|
||||
" <!ENTITY e2 '&e1;'>\n"
|
||||
"]><a k1='&e2;' />\n",
|
||||
false},
|
||||
|
||||
// parameter entity
|
||||
{"<!DOCTYPE doc [\n"
|
||||
" <!ENTITY % p1 '%p2;'>\n"
|
||||
" <!ENTITY % p2 '%p1;'>\n"
|
||||
" <!ENTITY % define_g \"<!ENTITY g '%p2;'>\">\n"
|
||||
" %define_g;\n"
|
||||
"]>\n"
|
||||
"<doc/>\n",
|
||||
true},
|
||||
};
|
||||
const XML_Bool reset_or_not[] = {XML_TRUE, XML_FALSE};
|
||||
|
||||
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
for (size_t j = 0; j < sizeof(reset_or_not) / sizeof(reset_or_not[0]);
|
||||
j++) {
|
||||
const XML_Bool reset_wanted = reset_or_not[j];
|
||||
const char *const doc = cases[i].doc;
|
||||
const bool usesParameterEntities = cases[i].usesParameterEntities;
|
||||
|
||||
set_subtest("[%i,reset=%i] %s", (int)i, (int)j, doc);
|
||||
|
||||
#ifdef XML_DTD // both GE and DTD
|
||||
const bool rejection_expected = true;
|
||||
#elif XML_GE == 1 // GE but not DTD
|
||||
const bool rejection_expected = ! usesParameterEntities;
|
||||
#else // neither DTD nor GE
|
||||
const bool rejection_expected = false;
|
||||
#endif
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
#ifdef XML_DTD
|
||||
if (usesParameterEntities) {
|
||||
assert_true(
|
||||
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS)
|
||||
== 1);
|
||||
}
|
||||
#else
|
||||
UNUSED_P(usesParameterEntities);
|
||||
#endif // XML_DTD
|
||||
|
||||
const enum XML_Status status
|
||||
= _XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||
/*isFinal*/ XML_TRUE);
|
||||
|
||||
if (rejection_expected) {
|
||||
assert_true(status == XML_STATUS_ERROR);
|
||||
assert_true(XML_GetErrorCode(parser) == XML_ERROR_RECURSIVE_ENTITY_REF);
|
||||
} else {
|
||||
assert_true(status == XML_STATUS_OK);
|
||||
}
|
||||
|
||||
if (reset_wanted) {
|
||||
// This covers free'ing of (eventually) all three open entity lists by
|
||||
// XML_ParserReset.
|
||||
XML_ParserReset(parser, NULL);
|
||||
}
|
||||
|
||||
// This covers free'ing of (eventually) all three open entity lists by
|
||||
// XML_ParserFree (unless XML_ParserReset has already done that above).
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_recursive_external_parameter_entity_2) {
|
||||
struct TestCase {
|
||||
const char *doc;
|
||||
enum XML_Status expectedStatus;
|
||||
};
|
||||
|
||||
struct TestCase cases[] = {
|
||||
{"<!ENTITY % p1 '%p1;'>", XML_STATUS_ERROR},
|
||||
{"<!ENTITY % p1 '%p1;'>"
|
||||
"<!ENTITY % p1 'first declaration wins'>",
|
||||
XML_STATUS_ERROR},
|
||||
{"<!ENTITY % p1 'first declaration wins'>"
|
||||
"<!ENTITY % p1 '%p1;'>",
|
||||
XML_STATUS_OK},
|
||||
{"<!ENTITY % p1 '%p1;'>", XML_STATUS_OK},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
const char *const doc = cases[i].doc;
|
||||
const enum XML_Status expectedStatus = cases[i].expectedStatus;
|
||||
set_subtest("%s", doc);
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
|
||||
XML_Parser ext_parser = XML_ExternalEntityParserCreate(parser, NULL, NULL);
|
||||
assert_true(ext_parser != NULL);
|
||||
|
||||
const enum XML_Status actualStatus
|
||||
= _XML_Parse_SINGLE_BYTES(ext_parser, doc, (int)strlen(doc), XML_TRUE);
|
||||
|
||||
assert_true(actualStatus == expectedStatus);
|
||||
if (actualStatus != XML_STATUS_OK) {
|
||||
assert_true(XML_GetErrorCode(ext_parser)
|
||||
== XML_ERROR_RECURSIVE_ENTITY_REF);
|
||||
}
|
||||
|
||||
XML_ParserFree(ext_parser);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test incomplete external entities are faulted */
|
||||
START_TEST(test_ext_entity_invalid_parse) {
|
||||
const char *text = "<!DOCTYPE doc [\n"
|
||||
@@ -1374,7 +1521,9 @@ START_TEST(test_suspend_parser_between_char_data_calls) {
|
||||
|
||||
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
|
||||
g_resumable = XML_TRUE;
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
!= XML_STATUS_SUSPENDED)
|
||||
xml_failure(g_parser);
|
||||
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
|
||||
@@ -1403,7 +1552,9 @@ START_TEST(test_repeated_stop_parser_between_char_data_calls) {
|
||||
XML_SetCharacterDataHandler(g_parser, parser_stop_character_handler);
|
||||
g_resumable = XML_TRUE;
|
||||
g_abortable = XML_FALSE;
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
!= XML_STATUS_SUSPENDED)
|
||||
fail("Failed to double-suspend parser");
|
||||
|
||||
@@ -1787,12 +1938,19 @@ END_TEST
|
||||
|
||||
/* Test suspending the parser in cdata handler */
|
||||
START_TEST(test_suspend_parser_between_cdata_calls) {
|
||||
if (g_chunkSize != 0) {
|
||||
// this test does not use SINGLE_BYTES, because of suspension
|
||||
return;
|
||||
}
|
||||
|
||||
const char *text = long_cdata_text;
|
||||
enum XML_Status result;
|
||||
|
||||
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
|
||||
g_resumable = XML_TRUE;
|
||||
result = _XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE);
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
result = XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE);
|
||||
if (result != XML_STATUS_SUSPENDED) {
|
||||
if (result == XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
@@ -2314,11 +2472,20 @@ START_TEST(test_attributes) {
|
||||
info[0].attributes = doc_info;
|
||||
info[1].attributes = tag_info;
|
||||
|
||||
XML_SetStartElementHandler(g_parser, counting_start_element_handler);
|
||||
XML_SetUserData(g_parser, info);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
ParserAndElementInfo parserAndElementInfos = {
|
||||
parser,
|
||||
info,
|
||||
};
|
||||
|
||||
XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
XML_SetUserData(parser, &parserAndElementInfos);
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
xml_failure(parser);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -2326,6 +2493,11 @@ END_TEST
|
||||
* entity. Exercises some obscure code in XML_ParserReset().
|
||||
*/
|
||||
START_TEST(test_reset_in_entity) {
|
||||
if (g_chunkSize != 0) {
|
||||
// this test does not use SINGLE_BYTES, because of suspension
|
||||
return;
|
||||
}
|
||||
|
||||
const char *text = "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY wombat 'wom'>\n"
|
||||
"<!ENTITY entity 'hi &wom; there'>\n"
|
||||
@@ -2335,7 +2507,9 @@ START_TEST(test_reset_in_entity) {
|
||||
|
||||
g_resumable = XML_TRUE;
|
||||
XML_SetCharacterDataHandler(g_parser, clearing_aborting_character_handler);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(g_parser);
|
||||
XML_GetParsingStatus(g_parser, &status);
|
||||
@@ -2761,6 +2935,61 @@ START_TEST(test_empty_parse) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test XML_Parse for len < 0 */
|
||||
START_TEST(test_negative_len_parse) {
|
||||
const char *const doc = "<root/>";
|
||||
for (int isFinal = 0; isFinal < 2; isFinal++) {
|
||||
set_subtest("isFinal=%d", isFinal);
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
|
||||
fail("There was not supposed to be any initial parse error.");
|
||||
|
||||
const enum XML_Status status = XML_Parse(parser, doc, -1, isFinal);
|
||||
|
||||
if (status != XML_STATUS_ERROR)
|
||||
fail("Negative len was expected to fail the parse but did not.");
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
|
||||
fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test XML_ParseBuffer for len < 0 */
|
||||
START_TEST(test_negative_len_parse_buffer) {
|
||||
const char *const doc = "<root/>";
|
||||
for (int isFinal = 0; isFinal < 2; isFinal++) {
|
||||
set_subtest("isFinal=%d", isFinal);
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_NONE)
|
||||
fail("There was not supposed to be any initial parse error.");
|
||||
|
||||
void *const buffer = XML_GetBuffer(parser, (int)strlen(doc));
|
||||
|
||||
if (buffer == NULL)
|
||||
fail("XML_GetBuffer failed.");
|
||||
|
||||
memcpy(buffer, doc, strlen(doc));
|
||||
|
||||
const enum XML_Status status = XML_ParseBuffer(parser, -1, isFinal);
|
||||
|
||||
if (status != XML_STATUS_ERROR)
|
||||
fail("Negative len was expected to fail the parse but did not.");
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_ARGUMENT)
|
||||
fail("Parse error does not match XML_ERROR_INVALID_ARGUMENT.");
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test odd corners of the XML_GetBuffer interface */
|
||||
static enum XML_Status
|
||||
get_feature(enum XML_FeatureEnum feature_id, long *presult) {
|
||||
@@ -3527,7 +3756,9 @@ START_TEST(test_suspend_xdecl) {
|
||||
XML_SetXmlDeclHandler(g_parser, entity_suspending_xdecl_handler);
|
||||
XML_SetUserData(g_parser, g_parser);
|
||||
g_resumable = XML_TRUE;
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
!= XML_STATUS_SUSPENDED)
|
||||
xml_failure(g_parser);
|
||||
if (XML_GetErrorCode(g_parser) != XML_ERROR_NONE)
|
||||
@@ -3723,13 +3954,20 @@ END_TEST
|
||||
|
||||
/* Test syntax error is caught at parse resumption */
|
||||
START_TEST(test_resume_entity_with_syntax_error) {
|
||||
if (g_chunkSize != 0) {
|
||||
// this test does not use SINGLE_BYTES, because of suspension
|
||||
return;
|
||||
}
|
||||
|
||||
const char *text = "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY foo '<suspend>Hi</wombat>'>\n"
|
||||
"]>\n"
|
||||
"<doc>&foo;</doc>\n";
|
||||
|
||||
XML_SetStartElementHandler(g_parser, start_element_suspender);
|
||||
if (_XML_Parse_SINGLE_BYTES(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
// can't use SINGLE_BYTES here, because it'll return early on suspension, and
|
||||
// we won't know exactly how much input we actually managed to give Expat.
|
||||
if (XML_Parse(g_parser, text, (int)strlen(text), XML_TRUE)
|
||||
!= XML_STATUS_SUSPENDED)
|
||||
xml_failure(g_parser);
|
||||
if (XML_ResumeParser(g_parser) != XML_STATUS_ERROR)
|
||||
@@ -3853,7 +4091,7 @@ START_TEST(test_skipped_null_loaded_ext_entity) {
|
||||
= {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
|
||||
"<!ENTITY % pe2 '%pe1;'>\n"
|
||||
"%pe2;\n",
|
||||
external_entity_null_loader};
|
||||
external_entity_null_loader, NULL};
|
||||
|
||||
XML_SetUserData(g_parser, &test_data);
|
||||
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
@@ -3871,7 +4109,7 @@ START_TEST(test_skipped_unloaded_ext_entity) {
|
||||
= {"<!ENTITY % pe1 SYSTEM 'http://example.org/two.ent'>\n"
|
||||
"<!ENTITY % pe2 '%pe1;'>\n"
|
||||
"%pe2;\n",
|
||||
NULL};
|
||||
NULL, NULL};
|
||||
|
||||
XML_SetUserData(g_parser, &test_data);
|
||||
XML_SetParamEntityParsing(g_parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
@@ -5171,6 +5409,151 @@ START_TEST(test_pool_integrity_with_unfinished_attr) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test a possible early return location in internalEntityProcessor */
|
||||
START_TEST(test_entity_ref_no_elements) {
|
||||
const char *const text = "<!DOCTYPE foo [\n"
|
||||
"<!ENTITY e1 \"test\">\n"
|
||||
"]> <foo>&e1;"; // intentionally missing newline
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR);
|
||||
assert_true(XML_GetErrorCode(parser) == XML_ERROR_NO_ELEMENTS);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Tests if chained entity references lead to unbounded recursion */
|
||||
START_TEST(test_deep_nested_entity) {
|
||||
const size_t N_LINES = 60000;
|
||||
const size_t SIZE_PER_LINE = 50;
|
||||
|
||||
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
|
||||
if (text == NULL) {
|
||||
fail("malloc failed");
|
||||
}
|
||||
|
||||
char *textPtr = text;
|
||||
|
||||
// Create the XML
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE,
|
||||
"<!DOCTYPE foo [\n"
|
||||
" <!ENTITY s0 'deepText'>\n");
|
||||
|
||||
for (size_t i = 1; i < N_LINES; ++i) {
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE, " <!ENTITY s%lu '&s%lu;'>\n",
|
||||
(long unsigned)i, (long unsigned)(i - 1));
|
||||
}
|
||||
|
||||
snprintf(textPtr, SIZE_PER_LINE, "]> <foo>&s%lu;</foo>\n",
|
||||
(long unsigned)(N_LINES - 1));
|
||||
|
||||
const XML_Char *const expected = XCS("deepText");
|
||||
|
||||
CharData storage;
|
||||
CharData_Init(&storage);
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetCharacterDataHandler(parser, accumulate_characters);
|
||||
XML_SetUserData(parser, &storage);
|
||||
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(parser);
|
||||
|
||||
CharData_CheckXMLChars(&storage, expected);
|
||||
XML_ParserFree(parser);
|
||||
free(text);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Tests if chained entity references in attributes
|
||||
lead to unbounded recursion */
|
||||
START_TEST(test_deep_nested_attribute_entity) {
|
||||
const size_t N_LINES = 60000;
|
||||
const size_t SIZE_PER_LINE = 100;
|
||||
|
||||
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
|
||||
if (text == NULL) {
|
||||
fail("malloc failed");
|
||||
}
|
||||
|
||||
char *textPtr = text;
|
||||
|
||||
// Create the XML
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE,
|
||||
"<!DOCTYPE foo [\n"
|
||||
" <!ENTITY s0 'deepText'>\n");
|
||||
|
||||
for (size_t i = 1; i < N_LINES; ++i) {
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE, " <!ENTITY s%lu '&s%lu;'>\n",
|
||||
(long unsigned)i, (long unsigned)(i - 1));
|
||||
}
|
||||
|
||||
snprintf(textPtr, SIZE_PER_LINE, "]> <foo name='&s%lu;'>mainText</foo>\n",
|
||||
(long unsigned)(N_LINES - 1));
|
||||
|
||||
AttrInfo doc_info[] = {{XCS("name"), XCS("deepText")}, {NULL, NULL}};
|
||||
ElementInfo info[] = {{XCS("foo"), 1, NULL, NULL}, {NULL, 0, NULL, NULL}};
|
||||
info[0].attributes = doc_info;
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
ParserAndElementInfo parserPlusElemenInfo = {parser, info};
|
||||
|
||||
XML_SetStartElementHandler(parser, counting_start_element_handler);
|
||||
XML_SetUserData(parser, &parserPlusElemenInfo);
|
||||
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(parser);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
free(text);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_deep_nested_entity_delayed_interpretation) {
|
||||
const size_t N_LINES = 70000;
|
||||
const size_t SIZE_PER_LINE = 100;
|
||||
|
||||
char *const text = (char *)malloc((N_LINES + 4) * SIZE_PER_LINE);
|
||||
if (text == NULL) {
|
||||
fail("malloc failed");
|
||||
}
|
||||
|
||||
char *textPtr = text;
|
||||
|
||||
// Create the XML
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE,
|
||||
"<!DOCTYPE foo [\n"
|
||||
" <!ENTITY %% s0 'deepText'>\n");
|
||||
|
||||
for (size_t i = 1; i < N_LINES; ++i) {
|
||||
textPtr += snprintf(textPtr, SIZE_PER_LINE,
|
||||
" <!ENTITY %% s%lu '%s%lu;'>\n", (long unsigned)i,
|
||||
(long unsigned)(i - 1));
|
||||
}
|
||||
|
||||
snprintf(textPtr, SIZE_PER_LINE,
|
||||
" <!ENTITY %% define_g \"<!ENTITY g '%s%lu;'>\">\n"
|
||||
" %%define_g;\n"
|
||||
"]>\n"
|
||||
"<foo/>\n",
|
||||
(long unsigned)(N_LINES - 1));
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(parser);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
free(text);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_nested_entity_suspend) {
|
||||
const char *const text = "<!DOCTYPE a [\n"
|
||||
" <!ENTITY e1 '<!--e1-->'>\n"
|
||||
@@ -5201,14 +5584,37 @@ START_TEST(test_nested_entity_suspend) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_nested_entity_suspend_2) {
|
||||
const char *const text = "<!DOCTYPE doc [\n"
|
||||
" <!ENTITY ge1 'head1Ztail1'>\n"
|
||||
" <!ENTITY ge2 'head2&ge1;tail2'>\n"
|
||||
" <!ENTITY ge3 'head3&ge2;tail3'>\n"
|
||||
"]>\n"
|
||||
"<doc>&ge3;</doc>";
|
||||
const XML_Char *const expected = XCS("head3") XCS("head2") XCS("head1")
|
||||
XCS("Z") XCS("tail1") XCS("tail2") XCS("tail3");
|
||||
CharData storage;
|
||||
CharData_Init(&storage);
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
ParserPlusStorage parserPlusStorage = {parser, &storage};
|
||||
|
||||
XML_SetCharacterDataHandler(parser, accumulate_char_data_and_suspend);
|
||||
XML_SetUserData(parser, &parserPlusStorage);
|
||||
|
||||
enum XML_Status status = XML_Parse(parser, text, (int)strlen(text), XML_TRUE);
|
||||
while (status == XML_STATUS_SUSPENDED) {
|
||||
status = XML_ResumeParser(parser);
|
||||
}
|
||||
if (status != XML_STATUS_OK)
|
||||
xml_failure(parser);
|
||||
|
||||
CharData_CheckXMLChars(&storage, expected);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Regression test for quadratic parsing on large tokens */
|
||||
START_TEST(test_big_tokens_take_linear_time) {
|
||||
const char *const too_slow_failure_message
|
||||
= "Compared to the baseline runtime of the first test, this test has a "
|
||||
"slowdown of more than <max_slowdown>. "
|
||||
"Please keep increasing the value by 1 until it reliably passes the "
|
||||
"test on your hardware and open a bug sharing that number with us. "
|
||||
"Thanks in advance!";
|
||||
START_TEST(test_big_tokens_scale_linearly) {
|
||||
const struct {
|
||||
const char *pre;
|
||||
const char *post;
|
||||
@@ -5220,65 +5626,57 @@ START_TEST(test_big_tokens_take_linear_time) {
|
||||
{"<e><", "/></e>"}, // big elem name, used to be O(N²)
|
||||
};
|
||||
const int num_cases = sizeof(text) / sizeof(text[0]);
|
||||
// For the test we need a <max_slowdown> value that is:
|
||||
// (1) big enough that the test passes reliably (avoiding flaky tests), and
|
||||
// (2) small enough that the test actually catches regressions.
|
||||
const int max_slowdown = 15;
|
||||
char aaaaaa[4096];
|
||||
const int fillsize = (int)sizeof(aaaaaa);
|
||||
const int fillcount = 100;
|
||||
const unsigned approx_bytes = fillsize * fillcount; // ignore pre/post.
|
||||
const unsigned max_factor = 4;
|
||||
const unsigned max_scanned = max_factor * approx_bytes;
|
||||
|
||||
memset(aaaaaa, 'a', fillsize);
|
||||
|
||||
if (! g_reparseDeferralEnabledDefault) {
|
||||
return; // heuristic is disabled; we would get O(n^2) and fail.
|
||||
}
|
||||
#if ! defined(__linux__)
|
||||
if (CLOCKS_PER_SEC < 100000) {
|
||||
// Skip this test if clock() doesn't have reasonably good resolution.
|
||||
// This workaround is primarily targeting Windows and FreeBSD, since
|
||||
// XSI requires the value to be 1.000.000 (10x the condition here), and
|
||||
// we want to be very sure that at least one platform in CI can catch
|
||||
// regressions (through a failing test).
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
clock_t baseline = 0;
|
||||
for (int i = 0; i < num_cases; ++i) {
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
enum XML_Status status;
|
||||
set_subtest("max_slowdown=%d text=\"%saaaaaa%s\"", max_slowdown,
|
||||
text[i].pre, text[i].post);
|
||||
const clock_t start = clock();
|
||||
set_subtest("text=\"%saaaaaa%s\"", text[i].pre, text[i].post);
|
||||
|
||||
// parse the start text
|
||||
g_bytesScanned = 0;
|
||||
status = _XML_Parse_SINGLE_BYTES(parser, text[i].pre,
|
||||
(int)strlen(text[i].pre), XML_FALSE);
|
||||
if (status != XML_STATUS_OK) {
|
||||
xml_failure(parser);
|
||||
}
|
||||
|
||||
// parse lots of 'a', failing the test early if it takes too long
|
||||
unsigned past_max_count = 0;
|
||||
for (int f = 0; f < fillcount; ++f) {
|
||||
status = _XML_Parse_SINGLE_BYTES(parser, aaaaaa, fillsize, XML_FALSE);
|
||||
if (status != XML_STATUS_OK) {
|
||||
xml_failure(parser);
|
||||
}
|
||||
// i == 0 means we're still calculating the baseline value
|
||||
if (i > 0) {
|
||||
const clock_t now = clock();
|
||||
const clock_t clocks_so_far = now - start;
|
||||
const int slowdown = clocks_so_far / baseline;
|
||||
if (slowdown >= max_slowdown) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"fill#%d: clocks_so_far=%d baseline=%d slowdown=%d max_slowdown=%d\n",
|
||||
f, (int)clocks_so_far, (int)baseline, slowdown, max_slowdown);
|
||||
fail(too_slow_failure_message);
|
||||
}
|
||||
if (g_bytesScanned > max_scanned) {
|
||||
// We're not done, and have already passed the limit -- the test will
|
||||
// definitely fail. This block allows us to save time by failing early.
|
||||
const unsigned pushed
|
||||
= (unsigned)strlen(text[i].pre) + (f + 1) * fillsize;
|
||||
fprintf(
|
||||
stderr,
|
||||
"after %d/%d loops: pushed=%u scanned=%u (factor ~%.2f) max_scanned: %u (factor ~%u)\n",
|
||||
f + 1, fillcount, pushed, g_bytesScanned,
|
||||
g_bytesScanned / (double)pushed, max_scanned, max_factor);
|
||||
past_max_count++;
|
||||
// We are failing, but allow a few log prints first. If we don't reach
|
||||
// a count of five, the test will fail after the loop instead.
|
||||
assert_true(past_max_count < 5);
|
||||
}
|
||||
}
|
||||
|
||||
// parse the end text
|
||||
status = _XML_Parse_SINGLE_BYTES(parser, text[i].post,
|
||||
(int)strlen(text[i].post), XML_TRUE);
|
||||
@@ -5286,18 +5684,14 @@ START_TEST(test_big_tokens_take_linear_time) {
|
||||
xml_failure(parser);
|
||||
}
|
||||
|
||||
// how long did it take in total?
|
||||
const clock_t end = clock();
|
||||
const clock_t taken = end - start;
|
||||
if (i == 0) {
|
||||
assert_true(taken > 0); // just to make sure we don't div-by-0 later
|
||||
baseline = taken;
|
||||
}
|
||||
const int slowdown = taken / baseline;
|
||||
if (slowdown >= max_slowdown) {
|
||||
fprintf(stderr, "taken=%d baseline=%d slowdown=%d max_slowdown=%d\n",
|
||||
(int)taken, (int)baseline, slowdown, max_slowdown);
|
||||
fail(too_slow_failure_message);
|
||||
assert_true(g_bytesScanned > approx_bytes); // or the counter isn't working
|
||||
if (g_bytesScanned > max_scanned) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"after all input: scanned=%u (factor ~%.2f) max_scanned: %u (factor ~%u)\n",
|
||||
g_bytesScanned, g_bytesScanned / (double)approx_bytes, max_scanned,
|
||||
max_factor);
|
||||
fail("scanned too many bytes");
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
@@ -5774,19 +6168,17 @@ START_TEST(test_varying_buffer_fills) {
|
||||
fillsize[2], fillsize[3]);
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
g_parseAttempts = 0;
|
||||
|
||||
CharData storage;
|
||||
CharData_Init(&storage);
|
||||
XML_SetUserData(parser, &storage);
|
||||
XML_SetStartElementHandler(parser, start_element_event_handler);
|
||||
|
||||
g_bytesScanned = 0;
|
||||
int worstcase_bytes = 0; // sum of (buffered bytes at each XML_Parse call)
|
||||
int scanned_bytes = 0; // sum of (buffered bytes at each actual parse)
|
||||
int offset = 0;
|
||||
while (*fillsize >= 0) {
|
||||
assert_true(offset + *fillsize <= document_length); // or test is invalid
|
||||
const unsigned attempts_before = g_parseAttempts;
|
||||
const enum XML_Status status
|
||||
= XML_Parse(parser, &document[offset], *fillsize, XML_FALSE);
|
||||
if (status != XML_STATUS_OK) {
|
||||
@@ -5796,28 +6188,20 @@ START_TEST(test_varying_buffer_fills) {
|
||||
fillsize++;
|
||||
assert_true(offset <= INT_MAX - worstcase_bytes); // avoid overflow
|
||||
worstcase_bytes += offset; // we might've tried to parse all pending bytes
|
||||
if (g_parseAttempts != attempts_before) {
|
||||
assert_true(g_parseAttempts == attempts_before + 1); // max 1/XML_Parse
|
||||
assert_true(offset <= INT_MAX - scanned_bytes); // avoid overflow
|
||||
scanned_bytes += offset; // we *did* try to parse all pending bytes
|
||||
}
|
||||
}
|
||||
assert_true(storage.count == 1); // the big token should've been parsed
|
||||
assert_true(scanned_bytes > 0); // test-the-test: does our counter work?
|
||||
assert_true(g_bytesScanned > 0); // test-the-test: does our counter work?
|
||||
if (g_reparseDeferralEnabledDefault) {
|
||||
// heuristic is enabled; some XML_Parse calls may have deferred reparsing
|
||||
const int max_bytes_scanned = -*fillsize;
|
||||
if (scanned_bytes > max_bytes_scanned) {
|
||||
const unsigned max_bytes_scanned = -*fillsize;
|
||||
if (g_bytesScanned > max_bytes_scanned) {
|
||||
fprintf(stderr,
|
||||
"bytes scanned in parse attempts: actual=%d limit=%d \n",
|
||||
scanned_bytes, max_bytes_scanned);
|
||||
"bytes scanned in parse attempts: actual=%u limit=%u \n",
|
||||
g_bytesScanned, max_bytes_scanned);
|
||||
fail("too many bytes scanned in parse attempts");
|
||||
}
|
||||
assert_true(scanned_bytes <= worstcase_bytes);
|
||||
} else {
|
||||
// heuristic is disabled; every XML_Parse() will have reparsed
|
||||
assert_true(scanned_bytes == worstcase_bytes);
|
||||
}
|
||||
assert_true(g_bytesScanned <= (unsigned)worstcase_bytes);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
@@ -5889,7 +6273,9 @@ make_basic_test_case(Suite *s) {
|
||||
tcase_add_test(tc_basic, test_wfc_undeclared_entity_with_external_subset);
|
||||
tcase_add_test(tc_basic, test_not_standalone_handler_reject);
|
||||
tcase_add_test(tc_basic, test_not_standalone_handler_accept);
|
||||
tcase_add_test(tc_basic, test_entity_start_tag_level_greater_than_one);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_wfc_no_recursive_entity_refs);
|
||||
tcase_add_test(tc_basic, test_no_indirectly_recursive_entity_refs);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_invalid_parse);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_dtd_default_handling);
|
||||
tcase_add_test(tc_basic, test_dtd_attr_handling);
|
||||
@@ -5940,6 +6326,8 @@ make_basic_test_case(Suite *s) {
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_user_parameters);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_ext_entity_ref_parameter);
|
||||
tcase_add_test(tc_basic, test_empty_parse);
|
||||
tcase_add_test(tc_basic, test_negative_len_parse);
|
||||
tcase_add_test(tc_basic, test_negative_len_parse_buffer);
|
||||
tcase_add_test(tc_basic, test_get_buffer_1);
|
||||
tcase_add_test(tc_basic, test_get_buffer_2);
|
||||
#if XML_CONTEXT_BYTES > 0
|
||||
@@ -5972,6 +6360,8 @@ make_basic_test_case(Suite *s) {
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic, test_skipped_parameter_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic,
|
||||
test_recursive_external_parameter_entity);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic,
|
||||
test_recursive_external_parameter_entity_2);
|
||||
tcase_add_test(tc_basic, test_undefined_ext_entity_in_external_dtd);
|
||||
tcase_add_test(tc_basic, test_suspend_xdecl);
|
||||
tcase_add_test(tc_basic, test_abort_epilog);
|
||||
@@ -6064,8 +6454,14 @@ make_basic_test_case(Suite *s) {
|
||||
tcase_add_test(tc_basic, test_empty_element_abort);
|
||||
tcase_add_test__ifdef_xml_dtd(tc_basic,
|
||||
test_pool_integrity_with_unfinished_attr);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_entity_ref_no_elements);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_entity);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_deep_nested_attribute_entity);
|
||||
tcase_add_test__if_xml_ge(tc_basic,
|
||||
test_deep_nested_entity_delayed_interpretation);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_nested_entity_suspend);
|
||||
tcase_add_test(tc_basic, test_big_tokens_take_linear_time);
|
||||
tcase_add_test__if_xml_ge(tc_basic, test_nested_entity_suspend_2);
|
||||
tcase_add_test(tc_basic, test_big_tokens_scale_linearly);
|
||||
tcase_add_test(tc_basic, test_set_reparse_deferral);
|
||||
tcase_add_test(tc_basic, test_reparse_deferral_is_inherited);
|
||||
tcase_add_test(tc_basic, test_set_reparse_deferral_on_null_parser);
|
||||
|
||||
@@ -303,6 +303,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -316,7 +317,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
Copyright (c) 2003-2006 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2017-2023 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Licensed under the MIT license:
|
||||
|
||||
@@ -32,10 +32,18 @@
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#define _POSIX_C_SOURCE 1 // fdopen
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <io.h> // _open, _close
|
||||
#else
|
||||
# include <unistd.h> // close
|
||||
#endif
|
||||
|
||||
#include <fcntl.h> // open
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h> // ptrdiff_t
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "expat.h"
|
||||
@@ -52,17 +60,18 @@
|
||||
# define XML_FMT_STR "s"
|
||||
#endif
|
||||
|
||||
static void
|
||||
static int
|
||||
usage(const char *prog, int rc) {
|
||||
fprintf(stderr, "usage: %s [-n] filename bufferSize nr_of_loops\n", prog);
|
||||
exit(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
XML_Parser parser;
|
||||
char *XMLBuf, *XMLBufEnd, *XMLBufPtr;
|
||||
FILE *fd;
|
||||
int fd;
|
||||
FILE *file;
|
||||
struct stat fileAttr;
|
||||
int nrOfLoops, bufferSize, i, isFinal;
|
||||
size_t fileSize;
|
||||
@@ -76,34 +85,48 @@ main(int argc, char *argv[]) {
|
||||
ns = 1;
|
||||
j = 1;
|
||||
} else
|
||||
usage(argv[0], 1);
|
||||
return usage(argv[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != j + 4)
|
||||
usage(argv[0], 1);
|
||||
return usage(argv[0], 1);
|
||||
|
||||
if (stat(argv[j + 1], &fileAttr) != 0) {
|
||||
fprintf(stderr, "could not access file '%s'\n", argv[j + 1]);
|
||||
fd = open(argv[j + 1], O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
fd = fopen(argv[j + 1], "r");
|
||||
if (! fd) {
|
||||
fprintf(stderr, "could not open file '%s'\n", argv[j + 1]);
|
||||
exit(2);
|
||||
if (fstat(fd, &fileAttr) != 0) {
|
||||
close(fd);
|
||||
fprintf(stderr, "could not fstat file '%s'\n", argv[j + 1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
file = fdopen(fd, "r");
|
||||
if (! file) {
|
||||
close(fd);
|
||||
fprintf(stderr, "could not fdopen file '%s'\n", argv[j + 1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
bufferSize = atoi(argv[j + 2]);
|
||||
nrOfLoops = atoi(argv[j + 3]);
|
||||
if (bufferSize <= 0 || nrOfLoops <= 0) {
|
||||
fclose(file); // NOTE: this closes fd as well
|
||||
fprintf(stderr, "buffer size and nr of loops must be greater than zero.\n");
|
||||
exit(3);
|
||||
return 3;
|
||||
}
|
||||
|
||||
XMLBuf = malloc(fileAttr.st_size);
|
||||
fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, fd);
|
||||
fclose(fd);
|
||||
if (XMLBuf == NULL) {
|
||||
fclose(file); // NOTE: this closes fd as well
|
||||
fprintf(stderr, "ouf of memory.\n");
|
||||
return 5;
|
||||
}
|
||||
fileSize = fread(XMLBuf, sizeof(char), fileAttr.st_size, file);
|
||||
fclose(file); // NOTE: this closes fd as well
|
||||
|
||||
if (ns)
|
||||
parser = XML_ParserCreateNS(NULL, '!');
|
||||
@@ -132,7 +155,7 @@ main(int argc, char *argv[]) {
|
||||
XML_GetCurrentColumnNumber(parser));
|
||||
free(XMLBuf);
|
||||
XML_ParserFree(parser);
|
||||
exit(4);
|
||||
return 4;
|
||||
}
|
||||
XMLBufPtr += bufferSize;
|
||||
} while (! isFinal);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
|
||||
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
|
||||
@@ -42,6 +42,8 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h> // for SIZE_MAX
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -51,6 +53,7 @@
|
||||
#include "chardata.h"
|
||||
#include "minicheck.h"
|
||||
#include "common.h"
|
||||
#include "handlers.h"
|
||||
|
||||
/* Common test data */
|
||||
|
||||
@@ -201,6 +204,12 @@ _XML_Parse_SINGLE_BYTES(XML_Parser parser, const char *s, int len,
|
||||
for (; len > chunksize; len -= chunksize, s += chunksize) {
|
||||
enum XML_Status res = XML_Parse(parser, s, chunksize, XML_FALSE);
|
||||
if (res != XML_STATUS_OK) {
|
||||
if ((res == XML_STATUS_SUSPENDED) && (len > chunksize)) {
|
||||
fail("Use of function _XML_Parse_SINGLE_BYTES with a chunk size "
|
||||
"greater than 0 (from g_chunkSize) does not work well with "
|
||||
"suspension. Please consider use of plain XML_Parse at this "
|
||||
"place in your test, instead.");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -221,30 +230,6 @@ _expect_failure(const char *text, enum XML_Error errorCode,
|
||||
_xml_failure(g_parser, file, lineno);
|
||||
}
|
||||
|
||||
/* Character data support for handlers, built on top of the code in
|
||||
* chardata.c
|
||||
*/
|
||||
void XMLCALL
|
||||
accumulate_characters(void *userData, const XML_Char *s, int len) {
|
||||
CharData_AppendXMLChars((CharData *)userData, s, len);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
accumulate_attribute(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts) {
|
||||
CharData *storage = (CharData *)userData;
|
||||
UNUSED_P(name);
|
||||
/* Check there are attributes to deal with */
|
||||
if (atts == NULL)
|
||||
return;
|
||||
|
||||
while (storage->count < 0 && atts[0] != NULL) {
|
||||
/* "accumulate" the value of the first attribute we see */
|
||||
CharData_AppendXMLChars(storage, atts[1], -1);
|
||||
atts += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_run_character_check(const char *text, const XML_Char *expected,
|
||||
const char *file, int line) {
|
||||
@@ -273,12 +258,6 @@ _run_attribute_check(const char *text, const XML_Char *expected,
|
||||
CharData_CheckXMLChars(&storage, expected);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
|
||||
ExtTest *test_data = (ExtTest *)userData;
|
||||
accumulate_characters(test_data->storage, s, len);
|
||||
}
|
||||
|
||||
void
|
||||
_run_ext_character_check(const char *text, ExtTest *test_data,
|
||||
const XML_Char *expected, const char *file, int line) {
|
||||
@@ -323,3 +302,26 @@ duff_reallocator(void *ptr, size_t size) {
|
||||
g_reallocation_count--;
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
// Portable remake of strndup(3) for C99; does not care about space efficiency
|
||||
char *
|
||||
portable_strndup(const char *s, size_t n) {
|
||||
if ((s == NULL) || (n == SIZE_MAX)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *const buffer = (char *)malloc(n + 1);
|
||||
if (buffer == NULL) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
|
||||
memcpy(buffer, s, n);
|
||||
|
||||
buffer[n] = '\0';
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2023 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
|
||||
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
|
||||
@@ -111,12 +111,6 @@ extern void _expect_failure(const char *text, enum XML_Error errorCode,
|
||||
/* Support functions for handlers to collect up character and attribute data.
|
||||
*/
|
||||
|
||||
extern void XMLCALL accumulate_characters(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
|
||||
extern void XMLCALL accumulate_attribute(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
|
||||
extern void _run_character_check(const char *text, const XML_Char *expected,
|
||||
const char *file, int line);
|
||||
|
||||
@@ -135,9 +129,6 @@ typedef struct ExtTest {
|
||||
CharData *storage;
|
||||
} ExtTest;
|
||||
|
||||
extern void XMLCALL ext_accumulate_characters(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
|
||||
extern void _run_ext_character_check(const char *text, ExtTest *test_data,
|
||||
const XML_Char *expected, const char *file,
|
||||
int line);
|
||||
@@ -155,6 +146,8 @@ extern void *duff_allocator(size_t size);
|
||||
|
||||
extern void *duff_reallocator(void *ptr, size_t size);
|
||||
|
||||
extern char *portable_strndup(const char *s, size_t n);
|
||||
|
||||
#endif /* XML_COMMON_H */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -103,7 +103,9 @@ end_element_event_handler2(void *userData, const XML_Char *name) {
|
||||
void XMLCALL
|
||||
counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts) {
|
||||
ElementInfo *info = (ElementInfo *)userData;
|
||||
ParserAndElementInfo *const parserAndElementInfos
|
||||
= (ParserAndElementInfo *)userData;
|
||||
ElementInfo *info = parserAndElementInfos->info;
|
||||
AttrInfo *attr;
|
||||
int count, id, i;
|
||||
|
||||
@@ -120,12 +122,12 @@ counting_start_element_handler(void *userData, const XML_Char *name,
|
||||
* is possibly a little unexpected, but it is what the
|
||||
* documentation in expat.h tells us to expect.
|
||||
*/
|
||||
count = XML_GetSpecifiedAttributeCount(g_parser);
|
||||
count = XML_GetSpecifiedAttributeCount(parserAndElementInfos->parser);
|
||||
if (info->attr_count * 2 != count) {
|
||||
fail("Not got expected attribute count");
|
||||
return;
|
||||
}
|
||||
id = XML_GetIdAttributeIndex(g_parser);
|
||||
id = XML_GetIdAttributeIndex(parserAndElementInfos->parser);
|
||||
if (id == -1 && info->id_name != NULL) {
|
||||
fail("ID not present");
|
||||
return;
|
||||
@@ -1840,6 +1842,15 @@ element_decl_suspender(void *userData, const XML_Char *name,
|
||||
XML_FreeContentModel(g_parser, model);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
suspend_after_element_declaration(void *userData, const XML_Char *name,
|
||||
XML_Content *model) {
|
||||
UNUSED_P(name);
|
||||
XML_Parser parser = (XML_Parser)userData;
|
||||
assert_true(XML_StopParser(parser, /*resumable*/ XML_TRUE) == XML_STATUS_OK);
|
||||
XML_FreeContentModel(parser, model);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
accumulate_pi_characters(void *userData, const XML_Char *target,
|
||||
const XML_Char *data) {
|
||||
@@ -1881,9 +1892,17 @@ accumulate_entity_decl(void *userData, const XML_Char *entityName,
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
accumulate_char_data(void *userData, const XML_Char *s, int len) {
|
||||
CharData *const storage = (CharData *)userData;
|
||||
CharData_AppendXMLChars(storage, s, len);
|
||||
accumulate_char_data_and_suspend(void *userData, const XML_Char *s, int len) {
|
||||
ParserPlusStorage *const parserPlusStorage = (ParserPlusStorage *)userData;
|
||||
|
||||
CharData_AppendXMLChars(parserPlusStorage->storage, s, len);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (s[i] == 'Z') {
|
||||
XML_StopParser(parserPlusStorage->parser, /*resumable=*/XML_TRUE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
@@ -1910,6 +1929,34 @@ accumulate_start_element(void *userData, const XML_Char *name,
|
||||
CharData_AppendXMLChars(storage, XCS(")\n"), 2);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
accumulate_characters(void *userData, const XML_Char *s, int len) {
|
||||
CharData *const storage = (CharData *)userData;
|
||||
CharData_AppendXMLChars(storage, s, len);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
accumulate_attribute(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts) {
|
||||
CharData *const storage = (CharData *)userData;
|
||||
UNUSED_P(name);
|
||||
/* Check there are attributes to deal with */
|
||||
if (atts == NULL)
|
||||
return;
|
||||
|
||||
while (storage->count < 0 && atts[0] != NULL) {
|
||||
/* "accumulate" the value of the first attribute we see */
|
||||
CharData_AppendXMLChars(storage, atts[1], -1);
|
||||
atts += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
ext_accumulate_characters(void *userData, const XML_Char *s, int len) {
|
||||
ExtTest *const test_data = (ExtTest *)userData;
|
||||
accumulate_characters(test_data->storage, s, len);
|
||||
}
|
||||
|
||||
void XMLCALL
|
||||
checking_default_handler(void *userData, const XML_Char *s, int len) {
|
||||
DefaultCheck *data = (DefaultCheck *)userData;
|
||||
|
||||
@@ -92,6 +92,11 @@ typedef struct elementInfo {
|
||||
AttrInfo *attributes;
|
||||
} ElementInfo;
|
||||
|
||||
typedef struct StructParserAndElementInfo {
|
||||
XML_Parser parser;
|
||||
ElementInfo *info;
|
||||
} ParserAndElementInfo;
|
||||
|
||||
extern void XMLCALL counting_start_element_handler(void *userData,
|
||||
const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
@@ -320,6 +325,7 @@ extern int XMLCALL external_entity_devaluer(XML_Parser parser,
|
||||
typedef struct ext_hdlr_data {
|
||||
const char *parse_text;
|
||||
XML_ExternalEntityRefHandler handler;
|
||||
CharData *storage;
|
||||
} ExtHdlrData;
|
||||
|
||||
extern int XMLCALL external_entity_oneshot_loader(XML_Parser parser,
|
||||
@@ -552,6 +558,10 @@ extern void XMLCALL suspending_comment_handler(void *userData,
|
||||
extern void XMLCALL element_decl_suspender(void *userData, const XML_Char *name,
|
||||
XML_Content *model);
|
||||
|
||||
extern void XMLCALL suspend_after_element_declaration(void *userData,
|
||||
const XML_Char *name,
|
||||
XML_Content *model);
|
||||
|
||||
extern void XMLCALL accumulate_pi_characters(void *userData,
|
||||
const XML_Char *target,
|
||||
const XML_Char *data);
|
||||
@@ -564,13 +574,23 @@ extern void XMLCALL accumulate_entity_decl(
|
||||
const XML_Char *systemId, const XML_Char *publicId,
|
||||
const XML_Char *notationName);
|
||||
|
||||
extern void XMLCALL accumulate_char_data(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
extern void XMLCALL accumulate_char_data_and_suspend(void *userData,
|
||||
const XML_Char *s,
|
||||
int len);
|
||||
|
||||
extern void XMLCALL accumulate_start_element(void *userData,
|
||||
const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
|
||||
extern void XMLCALL accumulate_characters(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
|
||||
extern void XMLCALL accumulate_attribute(void *userData, const XML_Char *name,
|
||||
const XML_Char **atts);
|
||||
|
||||
extern void XMLCALL ext_accumulate_characters(void *userData, const XML_Char *s,
|
||||
int len);
|
||||
|
||||
typedef struct default_check {
|
||||
const XML_Char *expected;
|
||||
const int expectedLen;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
|
||||
Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2022 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
|
||||
Licensed under the MIT license:
|
||||
@@ -129,8 +129,10 @@ void _check_set_test_info(char const *function, char const *filename,
|
||||
* Prototypes for the actual implementation.
|
||||
*/
|
||||
|
||||
# if defined(__GNUC__)
|
||||
# if defined(__has_attribute)
|
||||
# if __has_attribute(noreturn)
|
||||
__attribute__((noreturn))
|
||||
# endif
|
||||
# endif
|
||||
void
|
||||
_fail(const char *file, int line, const char *msg);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
Copyright (c) 2003 Greg Stein <gstein@users.sourceforge.net>
|
||||
Copyright (c) 2005-2007 Steven Solie <steven@solie.ca>
|
||||
Copyright (c) 2005-2012 Karl Waclawek <karl@waclawek.net>
|
||||
Copyright (c) 2016-2024 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
|
||||
Copyright (c) 2017-2022 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2017 Joe Orton <jorton@redhat.com>
|
||||
Copyright (c) 2017 José Gutiérrez de la Concha <jose@zeroc.com>
|
||||
@@ -59,6 +59,9 @@
|
||||
#include "handlers.h"
|
||||
#include "misc_tests.h"
|
||||
|
||||
void XMLCALL accumulate_characters_ext_handler(void *userData,
|
||||
const XML_Char *s, int len);
|
||||
|
||||
/* Test that a failure to allocate the parser structure fails gracefully */
|
||||
START_TEST(test_misc_alloc_create_parser) {
|
||||
XML_Memory_Handling_Suite memsuite = {duff_allocator, realloc, free};
|
||||
@@ -208,7 +211,7 @@ START_TEST(test_misc_version) {
|
||||
if (! versions_equal(&read_version, &parsed_version))
|
||||
fail("Version mismatch");
|
||||
|
||||
if (xcstrcmp(version_text, XCS("expat_2.6.0"))) /* needs bump on releases */
|
||||
if (xcstrcmp(version_text, XCS("expat_2.7.1"))) /* needs bump on releases */
|
||||
fail("XML_*_VERSION in expat.h out of sync?\n");
|
||||
}
|
||||
END_TEST
|
||||
@@ -294,6 +297,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_1) {
|
||||
parser = XML_ParserCreate(NULL);
|
||||
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
|
||||
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
|
||||
assert_true(mydata != NULL);
|
||||
mydata->parser = parser;
|
||||
mydata->deep = 0;
|
||||
XML_SetUserData(parser, mydata);
|
||||
@@ -315,6 +319,7 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
|
||||
parser = XML_ParserCreate(NULL);
|
||||
XML_SetElementHandler(parser, start_element_issue_240, end_element_issue_240);
|
||||
mydata = (DataIssue240 *)malloc(sizeof(DataIssue240));
|
||||
assert_true(mydata != NULL);
|
||||
mydata->parser = parser;
|
||||
mydata->deep = 0;
|
||||
XML_SetUserData(parser, mydata);
|
||||
@@ -328,63 +333,119 @@ START_TEST(test_misc_stop_during_end_handler_issue_240_2) {
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_misc_deny_internal_entity_closing_doctype_issue_317) {
|
||||
const char *const inputOne = "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % e ']><d/>'>\n"
|
||||
"\n"
|
||||
"%e;";
|
||||
const char *const inputTwo = "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '&e1;'>\n"
|
||||
"\n"
|
||||
"%e2;";
|
||||
const char *const inputThree = "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % e ']><d'>\n"
|
||||
"\n"
|
||||
"%e;";
|
||||
const char *const inputIssue317 = "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY % foo ']>\n"
|
||||
"<doc>Hell<oc (#PCDATA)*>'>\n"
|
||||
"%foo;\n"
|
||||
"]>\n"
|
||||
"<doc>Hello, world</dVc>";
|
||||
const char *const inputOne
|
||||
= "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
|
||||
"%element_d;\n"
|
||||
"<!ENTITY % e ']><d/>'>\n"
|
||||
"\n"
|
||||
"%e;";
|
||||
const char *const inputTwo
|
||||
= "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
|
||||
"%element_d;\n"
|
||||
"<!ENTITY % e1 ']><d/>'><!ENTITY % e2 '%e1;'>\n"
|
||||
"\n"
|
||||
"%e2;";
|
||||
const char *const inputThree
|
||||
= "<!DOCTYPE d [\n"
|
||||
"<!ENTITY % element_d '<!ELEMENT d (#PCDATA)*>'>\n"
|
||||
"%element_d;\n"
|
||||
"<!ENTITY % e ']><d'>\n"
|
||||
"\n"
|
||||
"%e;/>";
|
||||
const char *const inputIssue317
|
||||
= "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY % element_doc '<!ELEMENT doc (#PCDATA)*>'>\n"
|
||||
"%element_doc;\n"
|
||||
"<!ENTITY % foo ']>\n"
|
||||
"<doc>Hell<oc (#PCDATA)*>'>\n"
|
||||
"%foo;\n"
|
||||
"]>\n"
|
||||
"<doc>Hello, world</dVc>";
|
||||
|
||||
const char *const inputs[] = {inputOne, inputTwo, inputThree, inputIssue317};
|
||||
const XML_Bool suspendOrNot[] = {XML_FALSE, XML_TRUE};
|
||||
size_t inputIndex = 0;
|
||||
|
||||
for (; inputIndex < sizeof(inputs) / sizeof(inputs[0]); inputIndex++) {
|
||||
set_subtest("%s", inputs[inputIndex]);
|
||||
XML_Parser parser;
|
||||
enum XML_Status parseResult;
|
||||
int setParamEntityResult;
|
||||
XML_Size lineNumber;
|
||||
XML_Size columnNumber;
|
||||
const char *const input = inputs[inputIndex];
|
||||
for (size_t suspendOrNotIndex = 0;
|
||||
suspendOrNotIndex < sizeof(suspendOrNot) / sizeof(suspendOrNot[0]);
|
||||
suspendOrNotIndex++) {
|
||||
const char *const input = inputs[inputIndex];
|
||||
const XML_Bool suspend = suspendOrNot[suspendOrNotIndex];
|
||||
if (suspend && (g_chunkSize > 0)) {
|
||||
// We cannot use _XML_Parse_SINGLE_BYTES below due to suspension, and
|
||||
// so chunk sizes >0 would only repeat the very same test
|
||||
// due to use of plain XML_Parse; we are saving upon that runtime:
|
||||
return;
|
||||
}
|
||||
|
||||
parser = XML_ParserCreate(NULL);
|
||||
setParamEntityResult
|
||||
= XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
if (setParamEntityResult != 1)
|
||||
fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
|
||||
set_subtest("[input=%d suspend=%s] %s", (int)inputIndex,
|
||||
suspend ? "true" : "false", input);
|
||||
XML_Parser parser;
|
||||
enum XML_Status parseResult;
|
||||
int setParamEntityResult;
|
||||
XML_Size lineNumber;
|
||||
XML_Size columnNumber;
|
||||
|
||||
parser = XML_ParserCreate(NULL);
|
||||
setParamEntityResult
|
||||
= XML_SetParamEntityParsing(parser, XML_PARAM_ENTITY_PARSING_ALWAYS);
|
||||
if (setParamEntityResult != 1)
|
||||
fail("Failed to set XML_PARAM_ENTITY_PARSING_ALWAYS.");
|
||||
|
||||
if (suspend) {
|
||||
XML_SetUserData(parser, parser);
|
||||
XML_SetElementDeclHandler(parser, suspend_after_element_declaration);
|
||||
}
|
||||
|
||||
if (suspend) {
|
||||
// can't use SINGLE_BYTES here, because it'll return early on
|
||||
// suspension, and we won't know exactly how much input we actually
|
||||
// managed to give Expat.
|
||||
parseResult = XML_Parse(parser, input, (int)strlen(input), 0);
|
||||
|
||||
while (parseResult == XML_STATUS_SUSPENDED) {
|
||||
parseResult = XML_ResumeParser(parser);
|
||||
}
|
||||
|
||||
if (parseResult != XML_STATUS_ERROR) {
|
||||
// can't use SINGLE_BYTES here, because it'll return early on
|
||||
// suspension, and we won't know exactly how much input we actually
|
||||
// managed to give Expat.
|
||||
parseResult = XML_Parse(parser, "", 0, 1);
|
||||
}
|
||||
|
||||
while (parseResult == XML_STATUS_SUSPENDED) {
|
||||
parseResult = XML_ResumeParser(parser);
|
||||
}
|
||||
} else {
|
||||
parseResult
|
||||
= _XML_Parse_SINGLE_BYTES(parser, input, (int)strlen(input), 0);
|
||||
|
||||
if (parseResult != XML_STATUS_ERROR) {
|
||||
parseResult = _XML_Parse_SINGLE_BYTES(parser, "", 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
parseResult = _XML_Parse_SINGLE_BYTES(parser, input, (int)strlen(input), 0);
|
||||
if (parseResult != XML_STATUS_ERROR) {
|
||||
parseResult = _XML_Parse_SINGLE_BYTES(parser, "", 0, 1);
|
||||
if (parseResult != XML_STATUS_ERROR) {
|
||||
fail("Parsing was expected to fail but succeeded.");
|
||||
}
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
|
||||
fail("Error code does not match XML_ERROR_INVALID_TOKEN");
|
||||
|
||||
lineNumber = XML_GetCurrentLineNumber(parser);
|
||||
if (lineNumber != 6)
|
||||
fail("XML_GetCurrentLineNumber does not work as expected.");
|
||||
|
||||
columnNumber = XML_GetCurrentColumnNumber(parser);
|
||||
if (columnNumber != 0)
|
||||
fail("XML_GetCurrentColumnNumber does not work as expected.");
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
|
||||
if (XML_GetErrorCode(parser) != XML_ERROR_INVALID_TOKEN)
|
||||
fail("Error code does not match XML_ERROR_INVALID_TOKEN");
|
||||
|
||||
lineNumber = XML_GetCurrentLineNumber(parser);
|
||||
if (lineNumber != 4)
|
||||
fail("XML_GetCurrentLineNumber does not work as expected.");
|
||||
|
||||
columnNumber = XML_GetCurrentColumnNumber(parser);
|
||||
if (columnNumber != 0)
|
||||
fail("XML_GetCurrentColumnNumber does not work as expected.");
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
@@ -447,7 +508,7 @@ START_TEST(test_misc_general_entities_support) {
|
||||
XML_SetExternalEntityRefHandler(parser,
|
||||
external_entity_failer__if_not_xml_ge);
|
||||
XML_SetEntityDeclHandler(parser, accumulate_entity_decl);
|
||||
XML_SetCharacterDataHandler(parser, accumulate_char_data);
|
||||
XML_SetCharacterDataHandler(parser, accumulate_characters);
|
||||
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc), XML_TRUE)
|
||||
!= XML_STATUS_OK) {
|
||||
@@ -496,6 +557,127 @@ START_TEST(test_misc_char_handler_stop_without_leak) {
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_misc_resumeparser_not_crashing) {
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
XML_GetBuffer(parser, 1);
|
||||
XML_StopParser(parser, /*resumable=*/XML_TRUE);
|
||||
XML_ResumeParser(parser); // could crash here, previously
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_misc_stopparser_rejects_unstarted_parser) {
|
||||
const XML_Bool cases[] = {XML_TRUE, XML_FALSE};
|
||||
for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
|
||||
const XML_Bool resumable = cases[i];
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(XML_GetErrorCode(parser) == XML_ERROR_NONE);
|
||||
assert_true(XML_StopParser(parser, resumable) == XML_STATUS_ERROR);
|
||||
assert_true(XML_GetErrorCode(parser) == XML_ERROR_NOT_STARTED);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Adaptation of accumulate_characters that takes ExtHdlrData input to work with
|
||||
* test_renter_loop_finite_content below */
|
||||
void XMLCALL
|
||||
accumulate_characters_ext_handler(void *userData, const XML_Char *s, int len) {
|
||||
ExtHdlrData *const test_data = (ExtHdlrData *)userData;
|
||||
CharData_AppendXMLChars(test_data->storage, s, len);
|
||||
}
|
||||
|
||||
/* Test that internalEntityProcessor does not re-enter forever;
|
||||
* based on files tests/xmlconf/xmltest/valid/ext-sa/012.{xml,ent} */
|
||||
START_TEST(test_renter_loop_finite_content) {
|
||||
CharData storage;
|
||||
CharData_Init(&storage);
|
||||
const char *const text = "<!DOCTYPE doc [\n"
|
||||
"<!ENTITY e1 '&e2;'>\n"
|
||||
"<!ENTITY e2 '&e3;'>\n"
|
||||
"<!ENTITY e3 SYSTEM '012.ent'>\n"
|
||||
"<!ENTITY e4 '&e5;'>\n"
|
||||
"<!ENTITY e5 '(e5)'>\n"
|
||||
"<!ELEMENT doc (#PCDATA)>\n"
|
||||
"]>\n"
|
||||
"<doc>&e1;</doc>\n";
|
||||
ExtHdlrData test_data = {"&e4;\n", external_entity_null_loader, &storage};
|
||||
const XML_Char *const expected = XCS("(e5)\n");
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
assert_true(parser != NULL);
|
||||
XML_SetUserData(parser, &test_data);
|
||||
XML_SetExternalEntityRefHandler(parser, external_entity_oneshot_loader);
|
||||
XML_SetCharacterDataHandler(parser, accumulate_characters_ext_handler);
|
||||
if (_XML_Parse_SINGLE_BYTES(parser, text, (int)strlen(text), XML_TRUE)
|
||||
== XML_STATUS_ERROR)
|
||||
xml_failure(parser);
|
||||
|
||||
CharData_CheckXMLChars(&storage, expected);
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
// Inspired by function XML_OriginalString of Perl's XML::Parser
|
||||
static char *
|
||||
dup_original_string(XML_Parser parser) {
|
||||
const int byte_count = XML_GetCurrentByteCount(parser);
|
||||
|
||||
assert_true(byte_count >= 0);
|
||||
|
||||
int offset = -1;
|
||||
int size = -1;
|
||||
|
||||
const char *const context = XML_GetInputContext(parser, &offset, &size);
|
||||
|
||||
#if XML_CONTEXT_BYTES > 0
|
||||
assert_true(context != NULL);
|
||||
assert_true(offset >= 0);
|
||||
assert_true(size >= 0);
|
||||
return portable_strndup(context + offset, byte_count);
|
||||
#else
|
||||
assert_true(context == NULL);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_characters_issue_980(void *userData, const XML_Char *s, int len) {
|
||||
(void)s;
|
||||
(void)len;
|
||||
XML_Parser parser = (XML_Parser)userData;
|
||||
|
||||
char *const original_string = dup_original_string(parser);
|
||||
|
||||
#if XML_CONTEXT_BYTES > 0
|
||||
assert_true(original_string != NULL);
|
||||
assert_true(strcmp(original_string, "&draft.day;") == 0);
|
||||
free(original_string);
|
||||
#else
|
||||
assert_true(original_string == NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
START_TEST(test_misc_expected_event_ptr_issue_980) {
|
||||
// NOTE: This is a tiny subset of sample "REC-xml-19980210.xml"
|
||||
// from Perl's XML::Parser
|
||||
const char *const doc = "<!DOCTYPE day [\n"
|
||||
" <!ENTITY draft.day '10'>\n"
|
||||
"]>\n"
|
||||
"<day>&draft.day;</day>\n";
|
||||
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
XML_SetUserData(parser, parser);
|
||||
XML_SetCharacterDataHandler(parser, on_characters_issue_980);
|
||||
|
||||
assert_true(_XML_Parse_SINGLE_BYTES(parser, doc, (int)strlen(doc),
|
||||
/*isFinal=*/XML_TRUE)
|
||||
== XML_STATUS_OK);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
make_miscellaneous_test_case(Suite *s) {
|
||||
TCase *tc_misc = tcase_create("miscellaneous tests");
|
||||
@@ -520,4 +702,8 @@ make_miscellaneous_test_case(Suite *s) {
|
||||
test_misc_create_external_entity_parser_with_null_context);
|
||||
tcase_add_test(tc_misc, test_misc_general_entities_support);
|
||||
tcase_add_test(tc_misc, test_misc_char_handler_stop_without_leak);
|
||||
tcase_add_test(tc_misc, test_misc_resumeparser_not_crashing);
|
||||
tcase_add_test(tc_misc, test_misc_stopparser_rejects_unstarted_parser);
|
||||
tcase_add_test__if_xml_ge(tc_misc, test_renter_loop_finite_content);
|
||||
tcase_add_test(tc_misc, test_misc_expected_event_ptr_issue_980);
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
# EXPAT TEST SCRIPT FOR W3C XML TEST SUITE
|
||||
#
|
||||
# This script can be used to exercise Expat against the
|
||||
# w3c.org xml test suite, available from
|
||||
# http://www.w3.org/XML/Test/xmlts20020606.zip.
|
||||
# w3c.org xml test suite, available from:
|
||||
# https://www.w3.org/XML/Test/xmlts20020606.zip
|
||||
#
|
||||
# To run this script, first set XMLWF below so that xmlwf can be
|
||||
# found, then set the output directory with OUTPUT.
|
||||
@@ -30,6 +30,7 @@
|
||||
# Copyright (c) 2002 Karl Waclawek <[email protected]>
|
||||
# Copyright (c) 2008-2019 Sebastian Pipping <[email protected]>
|
||||
# Copyright (c) 2017 Rhodri James <[email protected]>
|
||||
# Copyright (c) 2025 Hanno Böck <[email protected]>
|
||||
# Licensed under the MIT license:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
|
||||
@@ -311,6 +311,7 @@ RANLIB = @RANLIB@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SIZEOF_VOID_P = @SIZEOF_VOID_P@
|
||||
SO_MAJOR = @SO_MAJOR@
|
||||
SO_MINOR = @SO_MINOR@
|
||||
SO_PATCH = @SO_PATCH@
|
||||
@@ -324,7 +325,6 @@ ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
ac_cv_sizeof_void_p = @ac_cv_sizeof_void_p@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2017 Franek Korta <fkorta@gmail.com>
|
||||
Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
|
||||
Copyright (c) 2025 Hanno Böck <hanno@gentoo.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -55,7 +56,7 @@
|
||||
# define EXPAT_read_count_t int
|
||||
# define EXPAT_read_req_t unsigned int
|
||||
#else /* POSIX */
|
||||
/* http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */
|
||||
/* https://pubs.opengroup.org/onlinepubs/009695399/functions/read.html */
|
||||
# define EXPAT_read read
|
||||
# define EXPAT_read_count_t ssize_t
|
||||
# define EXPAT_read_req_t size_t
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
Copyright (c) 2017 Rhodri James <rhodri@wildebeest.org.uk>
|
||||
Copyright (c) 2019 David Loffredo <loffredo@steptools.com>
|
||||
Copyright (c) 2021 Donghee Na <donghee.na@python.org>
|
||||
Copyright (c) 2024 Hanno Böck <hanno@gentoo.org>
|
||||
Licensed under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
@@ -91,7 +92,8 @@ reportError(XML_Parser parser, const XML_Char *filename) {
|
||||
filename, XML_GetErrorLineNumber(parser),
|
||||
XML_GetErrorColumnNumber(parser), message);
|
||||
else
|
||||
ftprintf(stderr, T("%s: (unknown message %d)\n"), filename, code);
|
||||
ftprintf(stderr, T("%s: (unknown message %u)\n"), filename,
|
||||
(unsigned int)code);
|
||||
}
|
||||
|
||||
/* This implementation will give problems on files larger than INT_MAX. */
|
||||
|
||||
@@ -20,7 +20,7 @@ the actual statements in the files are controlling.
|
||||
libarchive/mtree.5
|
||||
|
||||
* The following source files are in the public domain:
|
||||
libarchive/archive_getdate.c
|
||||
libarchive/archive_parse_date.c
|
||||
|
||||
* The following source files are triple-licensed with the ability to choose
|
||||
from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
Jun 01, 2026: 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
|
||||
|
||||
@@ -85,13 +85,14 @@ Currently, the library automatically detects and reads the following formats:
|
||||
* PWB binary cpio
|
||||
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
|
||||
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
|
||||
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
|
||||
* ZIPX archives (with support for bzip2, zstd, ppmd8, lzma and xz compressed entries)
|
||||
* GNU and BSD 'ar' archives
|
||||
* 'mtree' format
|
||||
* 7-Zip archives (including archives that use zstandard compression)
|
||||
* Microsoft CAB format
|
||||
* LHA and LZH archives
|
||||
* RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status)
|
||||
* WARC archives
|
||||
* XAR archives
|
||||
|
||||
The library also detects and handles any of the following before evaluating the archive:
|
||||
@@ -120,15 +121,18 @@ The library can create archives in any of the following formats:
|
||||
* PWB binary cpio
|
||||
* shar archives
|
||||
* ZIP archives (with uncompressed or "deflate" compressed entries)
|
||||
* ZIPX archives (with bzip2, zstd, lzma or xz compressed entries)
|
||||
* GNU and BSD 'ar' archives
|
||||
* 'mtree' format
|
||||
* ISO9660 format
|
||||
* 7-Zip archives
|
||||
* 7-Zip archives (including archives that use zstandard compression)
|
||||
* WARC archives
|
||||
* XAR archives
|
||||
|
||||
When creating archives, the result can be filtered with any of the following:
|
||||
|
||||
* uuencode
|
||||
* base64
|
||||
* gzip compression
|
||||
* bzip2 compression
|
||||
* compress/LZW compression
|
||||
@@ -241,4 +245,3 @@ questions we are asked about libarchive:
|
||||
appropriate. It has many advantages over other tar formats
|
||||
(including the legacy GNU tar format) and is widely supported by
|
||||
current tar implementations.
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
|
||||
# Uncommenting these adds a full minute to the CI time
|
||||
#brew update > /dev/null
|
||||
#brew upgrade > /dev/null
|
||||
|
||||
# This does an upgrade if the package is already installed
|
||||
brew install \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
pkg-config \
|
||||
cmake \
|
||||
xz \
|
||||
lz4 \
|
||||
zstd \
|
||||
libxml2 \
|
||||
openssl
|
||||
@@ -1206,7 +1206,7 @@ list_item_verbose(struct cpio *cpio, struct archive_entry *entry)
|
||||
else
|
||||
strcpy(date, "invalid mtime");
|
||||
|
||||
fprintf(out, "%s%3d %-8s %-8s %8s %12s %s",
|
||||
fprintf(out, "%s%3u %-8s %-8s %8s %12s %s",
|
||||
archive_entry_strmode(entry),
|
||||
archive_entry_nlink(entry),
|
||||
uname, gname, size, date,
|
||||
|
||||
@@ -189,10 +189,10 @@ DEFINE_TEST(test_format_newc)
|
||||
gid = from_hex(e + 30, 8); /* gid */
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
t = from_hex(e + 46, 8); /* mtime */
|
||||
failure("t=%#08jx now=%#08jx=%jd", (intmax_t)t, (intmax_t)now,
|
||||
failure("t=%#08jx now=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now,
|
||||
(intmax_t)now);
|
||||
assert(t <= now); /* File wasn't created in future. */
|
||||
failure("t=%#08jx now - 2=%#08jx=%jd", (intmax_t)t, (intmax_t)now - 2,
|
||||
failure("t=%#08jx now - 2=%#08jx=%jd", (uintmax_t)t, (uintmax_t)now - 2,
|
||||
(intmax_t)now - 2);
|
||||
assert(t >= now - 2); /* File was created w/in last 2 secs. */
|
||||
failure("newc format stores body only with last appearance of a link\n"
|
||||
@@ -219,7 +219,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assert(is_hex(e, 110));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Mode: Group members bits and others bits do not work. */
|
||||
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
|
||||
#else
|
||||
@@ -230,7 +230,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assertEqualMem(e + 38, "00000001", 8); /* nlink */
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created"
|
||||
" at t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
" at t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualMem(e + 54, "00000005", 8); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
@@ -266,7 +266,7 @@ DEFINE_TEST(test_format_newc)
|
||||
#endif
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created at"
|
||||
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualMem(e + 54, "00000000", 8); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
@@ -300,7 +300,7 @@ DEFINE_TEST(test_format_newc)
|
||||
assertEqualMem(e + 38, "00000003", 8); /* nlink */
|
||||
t2 = from_hex(e + 46, 8); /* mtime */
|
||||
failure("First entry created at t=%#08jx this entry created at"
|
||||
"t2=%#08jx", (intmax_t)t, (intmax_t)t2);
|
||||
"t2=%#08jx", (uintmax_t)t, (uintmax_t)t2);
|
||||
assert(t2 == t || t2 == t + 1); /* Almost same as first entry. */
|
||||
assertEqualInt(10, from_hex(e + 54, 8)); /* File size */
|
||||
fs = (uint64_t)from_hex(e + 54, 8);
|
||||
|
||||
@@ -52,7 +52,7 @@ test_create(void)
|
||||
* #ifdef this section out. Most of the test below is
|
||||
* still valid. */
|
||||
memset(×, 0, sizeof(times));
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
times.actime = 86400;
|
||||
times.modtime = 86400;
|
||||
#else
|
||||
|
||||
@@ -18,7 +18,7 @@ is_octal(const char *p, size_t l)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static long long int
|
||||
static unsigned long long int
|
||||
from_octal(const char *p, size_t l)
|
||||
{
|
||||
long long int r = 0;
|
||||
@@ -117,7 +117,7 @@ DEFINE_TEST(test_option_c)
|
||||
gid = (int)from_octal(e + 30, 6);
|
||||
assertEqualMem(e + 36, "000001", 6); /* nlink */
|
||||
failure("file entries should not have rdev set (dev field was 0%o)",
|
||||
dev);
|
||||
(unsigned int)dev);
|
||||
assertEqualMem(e + 42, "000000", 6); /* rdev */
|
||||
t = from_octal(e + 48, 11); /* mtime */
|
||||
assert(t <= now); /* File wasn't created in future. */
|
||||
@@ -133,7 +133,7 @@ DEFINE_TEST(test_option_c)
|
||||
assert(is_octal(e, 76)); /* Entire header is octal digits. */
|
||||
assertEqualMem(e + 0, "070707", 6); /* Magic */
|
||||
assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */
|
||||
assert(ino != from_octal(e + 12, 6)); /* ino */
|
||||
assert(ino != (int)from_octal(e + 12, 6)); /* ino */
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
/* On Windows, symbolic link and group members bits and
|
||||
* others bits do not work. */
|
||||
@@ -163,7 +163,7 @@ DEFINE_TEST(test_option_c)
|
||||
assertEqualInt(dev, from_octal(e + 6, 6));
|
||||
/* Ino must be different from first entry. */
|
||||
assert(is_octal(e + 12, 6)); /* ino */
|
||||
assert(ino != from_octal(e + 12, 6));
|
||||
assert(ino != (int)from_octal(e + 12, 6));
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* Group members bits and others bits do not work. */
|
||||
assertEqualMem(e + 18, "040777", 6); /* Mode */
|
||||
|
||||
@@ -34,12 +34,15 @@
|
||||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3007007
|
||||
#define ARCHIVE_VERSION_NUMBER 3008001
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdio.h> /* For FILE * */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* time_t is slated to be removed from public includes in 4.0 */
|
||||
#include <time.h> /* For time_t */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: archive.h is for use outside of libarchive; the configuration
|
||||
@@ -63,12 +66,15 @@
|
||||
#define __LA_INT64_T_DEFINED
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
|
||||
typedef __int64 la_int64_t;
|
||||
typedef unsigned __int64 la_uint64_t;
|
||||
# else
|
||||
# include <unistd.h> /* ssize_t */
|
||||
# if defined(_SCO_DS) || defined(__osf__)
|
||||
typedef long long la_int64_t;
|
||||
typedef unsigned long long la_uint64_t;
|
||||
# else
|
||||
typedef int64_t la_int64_t;
|
||||
typedef uint64_t la_uint64_t;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@@ -94,6 +100,22 @@ typedef ssize_t la_ssize_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for time_t */
|
||||
#define __LA_TIME_T time_t
|
||||
#else
|
||||
/* Use 64-bits integer types for time_t */
|
||||
#define __LA_TIME_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for dev_t */
|
||||
#define __LA_DEV_T dev_t
|
||||
#else
|
||||
/* Use 64-bits integer types for dev_t */
|
||||
#define __LA_DEV_T la_int64_t
|
||||
#endif
|
||||
|
||||
/* Large file support for Android */
|
||||
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
|
||||
#include "android_lf.h"
|
||||
@@ -132,7 +154,7 @@ typedef ssize_t la_ssize_t;
|
||||
#define __LA_PRINTF(fmtarg, firstvararg) /* nothing */
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define __LA_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define __LA_DEPRECATED
|
||||
@@ -155,7 +177,7 @@ __LA_DECL int archive_version_number(void);
|
||||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.7.7"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.8.1"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
@@ -178,6 +200,23 @@ __LA_DECL const char * archive_liblzma_version(void);
|
||||
__LA_DECL const char * archive_bzlib_version(void);
|
||||
__LA_DECL const char * archive_liblz4_version(void);
|
||||
__LA_DECL const char * archive_libzstd_version(void);
|
||||
__LA_DECL const char * archive_liblzo2_version(void);
|
||||
__LA_DECL const char * archive_libexpat_version(void);
|
||||
__LA_DECL const char * archive_libbsdxml_version(void);
|
||||
__LA_DECL const char * archive_libxml2_version(void);
|
||||
__LA_DECL const char * archive_mbedtls_version(void);
|
||||
__LA_DECL const char * archive_nettle_version(void);
|
||||
__LA_DECL const char * archive_openssl_version(void);
|
||||
__LA_DECL const char * archive_libmd_version(void);
|
||||
__LA_DECL const char * archive_commoncrypto_version(void);
|
||||
__LA_DECL const char * archive_cng_version(void);
|
||||
__LA_DECL const char * archive_wincrypt_version(void);
|
||||
__LA_DECL const char * archive_librichacl_version(void);
|
||||
__LA_DECL const char * archive_libacl_version(void);
|
||||
__LA_DECL const char * archive_libattr_version(void);
|
||||
__LA_DECL const char * archive_libiconv_version(void);
|
||||
__LA_DECL const char * archive_libpcre_version(void);
|
||||
__LA_DECL const char * archive_libpcre2_version(void);
|
||||
|
||||
/* Declare our basic types. */
|
||||
struct archive;
|
||||
@@ -449,6 +488,8 @@ __LA_DECL int archive_read_support_format_by_code(struct archive *, int);
|
||||
__LA_DECL int archive_read_support_format_cab(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_cpio(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_empty(struct archive *);
|
||||
/* archive_read_support_format_gnutar() is an alias for historical reasons
|
||||
* of archive_read_support_format_tar(). */
|
||||
__LA_DECL int archive_read_support_format_gnutar(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_iso9660(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_lha(struct archive *);
|
||||
@@ -828,6 +869,10 @@ __LA_DECL int archive_write_set_format_filter_by_ext(struct archive *a, const ch
|
||||
__LA_DECL int archive_write_set_format_filter_by_ext_def(struct archive *a, const char *filename, const char * def_ext);
|
||||
__LA_DECL int archive_write_zip_set_compression_deflate(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_store(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_lzma(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_xz(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_bzip2(struct archive *);
|
||||
__LA_DECL int archive_write_zip_set_compression_zstd(struct archive *);
|
||||
/* Deprecated; use archive_write_open2 instead */
|
||||
__LA_DECL int archive_write_open(struct archive *, void *,
|
||||
archive_open_callback *, archive_write_callback *,
|
||||
@@ -1083,6 +1128,10 @@ __LA_DECL int archive_compression(struct archive *)
|
||||
__LA_DEPRECATED;
|
||||
#endif
|
||||
|
||||
/* Parses a date string relative to the current time.
|
||||
* NOTE: This is not intended for general date parsing, and the resulting timestamp should only be used for libarchive. */
|
||||
__LA_DECL time_t archive_parse_date(time_t now, const char *datestr);
|
||||
|
||||
__LA_DECL int archive_errno(struct archive *);
|
||||
__LA_DECL const char *archive_error_string(struct archive *);
|
||||
__LA_DECL const char *archive_format_name(struct archive *);
|
||||
@@ -1201,8 +1250,10 @@ __LA_DECL int archive_match_include_gname_w(struct archive *,
|
||||
const wchar_t *);
|
||||
|
||||
/* Utility functions */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Convenience function to sort a NULL terminated list of strings */
|
||||
__LA_DECL int archive_utility_string_sort(char **);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1185,8 +1185,13 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
|
||||
/* Set remaining fields to blank. */
|
||||
for (n = fields; n < numfields; ++n)
|
||||
field[n].start = field[n].end = NULL;
|
||||
|
||||
if (field[0].start == NULL || field[0].end == NULL) {
|
||||
/* This should never happen */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (field[0].start != NULL && *(field[0].start) == L'#') {
|
||||
if (*(field[0].start) == L'#') {
|
||||
/* Comment, skip entry */
|
||||
continue;
|
||||
}
|
||||
@@ -1676,7 +1681,12 @@ archive_acl_from_text_nl(struct archive_acl *acl, const char *text,
|
||||
for (n = fields; n < numfields; ++n)
|
||||
field[n].start = field[n].end = NULL;
|
||||
|
||||
if (field[0].start != NULL && *(field[0].start) == '#') {
|
||||
if (field[0].start == NULL || field[0].end == NULL) {
|
||||
/* This should never happen */
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (*(field[0].start) == '#') {
|
||||
/* Comment, skip entry */
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -80,4 +80,4 @@ int archive_acl_from_text_l(struct archive_acl *, const char * /* text */,
|
||||
int archive_acl_from_text_nl(struct archive_acl *, const char * /* text */,
|
||||
size_t /* size of text */, int /* type */, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ACL_PRIVATE_H_INCLUDED */
|
||||
@@ -71,7 +71,7 @@ get_argument(struct archive_string *as, const char *p)
|
||||
archive_string_empty(as);
|
||||
|
||||
/* Skip beginning space characters. */
|
||||
while (*s != '\0' && *s == ' ')
|
||||
while (*s == ' ')
|
||||
s++;
|
||||
/* Copy non-space characters. */
|
||||
while (*s != '\0' && *s != ' ') {
|
||||
|
||||
@@ -64,6 +64,7 @@ typedef struct {
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_CNG 1
|
||||
|
||||
/* Common in other bcrypt implementations, but missing from VS2008. */
|
||||
#ifndef BCRYPT_SUCCESS
|
||||
@@ -86,6 +87,7 @@ typedef struct {
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include <mbedtls/pkcs5.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_MBED 1
|
||||
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
#define AES_BLOCK_SIZE 16
|
||||
@@ -105,6 +107,7 @@ typedef struct {
|
||||
#endif
|
||||
#include <nettle/aes.h>
|
||||
#include <nettle/version.h>
|
||||
#define ARCHIVE_CRYPTOR_USE_NETTLE 1
|
||||
|
||||
typedef struct {
|
||||
#if NETTLE_VERSION_MAJOR < 3
|
||||
@@ -125,6 +128,7 @@ typedef struct {
|
||||
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
#include "archive_openssl_evp_private.h"
|
||||
#define ARCHIVE_CRYPTOR_USE_OPENSSL 1
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
|
||||
@@ -140,6 +144,10 @@ typedef struct {
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__) && !(defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA)
|
||||
#define ARCHIVE_CRYPTOR_USE_WINCRYPT 1
|
||||
#endif
|
||||
|
||||
#define AES_BLOCK_SIZE 16
|
||||
#define AES_MAX_KEY_SIZE 32
|
||||
typedef int archive_crypto_ctx;
|
||||
|
||||
@@ -196,6 +196,13 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
|
||||
|
||||
// These functions are available in macOS 10.4 and later, but deprecated from 10.15 onwards.
|
||||
// We need to continue supporting this feature regardless, so suppress the warnings.
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
@@ -218,13 +225,46 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 16, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
mbedtls_md5_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -234,7 +274,11 @@ static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_md5_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -243,7 +287,11 @@ __archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_md5_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_md5_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_md5_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -311,31 +359,6 @@ __archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
|
||||
static int
|
||||
__archive_md5init(archive_md5_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_MD5_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_MD5));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5update(archive_md5_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_md5final(archive_md5_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 16, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -420,7 +443,11 @@ static int
|
||||
__archive_ripemd160init(archive_rmd160_ctx *ctx)
|
||||
{
|
||||
mbedtls_ripemd160_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -430,7 +457,11 @@ static int
|
||||
__archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_ripemd160_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -439,7 +470,11 @@ __archive_ripemd160update(archive_rmd160_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_ripemd160final(archive_rmd160_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_ripemd160_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_ripemd160_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_ripemd160_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -605,13 +640,42 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 20, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha1_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_starts(ctx) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_starts_ret(ctx) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -621,7 +685,11 @@ static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha1_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -630,7 +698,11 @@ __archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha1_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha1_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha1_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -698,31 +770,6 @@ __archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha1init(archive_sha1_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA1_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_FULL, CALG_SHA1));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1update(archive_sha1_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha1final(archive_sha1_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 20, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -873,13 +920,42 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 32, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha256_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_starts_ret(ctx, 0) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -889,7 +965,11 @@ static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha256_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -898,7 +978,11 @@ __archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha256_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha256_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha256_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -962,31 +1046,6 @@ __archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha256init(archive_sha256_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA256_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_256));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256update(archive_sha256_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha256final(archive_sha256_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 32, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1113,13 +1172,42 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 48, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 1) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 1) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1129,7 +1217,11 @@ static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1138,7 +1230,11 @@ __archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha512_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -1202,31 +1298,6 @@ __archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha384init(archive_sha384_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA384_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_384));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384update(archive_sha384_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha384final(archive_sha384_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 48, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1377,13 +1448,42 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 64, ctx));
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
mbedtls_sha512_init(ctx);
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_starts(ctx, 0) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_starts_ret(ctx, 0) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1393,7 +1493,11 @@ static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_update(ctx, indata, insize) == 0)
|
||||
#else
|
||||
if (mbedtls_sha512_update_ret(ctx, indata, insize) == 0)
|
||||
#endif
|
||||
return (ARCHIVE_OK);
|
||||
else
|
||||
return (ARCHIVE_FATAL);
|
||||
@@ -1402,7 +1506,11 @@ __archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
#if MBEDTLS_VERSION_NUMBER > 0x03000000
|
||||
if (mbedtls_sha512_finish(ctx, md) == 0) {
|
||||
#else
|
||||
if (mbedtls_sha512_finish_ret(ctx, md) == 0) {
|
||||
#endif
|
||||
mbedtls_sha512_free(ctx);
|
||||
return (ARCHIVE_OK);
|
||||
} else {
|
||||
@@ -1466,31 +1574,6 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
|
||||
static int
|
||||
__archive_sha512init(archive_sha512_ctx *ctx)
|
||||
{
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
return (win_crypto_init(ctx, BCRYPT_SHA512_ALGORITHM));
|
||||
#else
|
||||
return (win_crypto_init(ctx, PROV_RSA_AES, CALG_SHA_512));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512update(archive_sha512_ctx *ctx, const void *indata,
|
||||
size_t insize)
|
||||
{
|
||||
return (win_crypto_Update(ctx, indata, insize));
|
||||
}
|
||||
|
||||
static int
|
||||
__archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
{
|
||||
return (win_crypto_Final(md, 64, ctx));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int
|
||||
@@ -1525,11 +1608,12 @@ __archive_sha512final(archive_sha512_ctx *ctx, void *md)
|
||||
* 1. libc
|
||||
* 2. libc2
|
||||
* 3. libc3
|
||||
* 4. libSystem
|
||||
* 5. Nettle
|
||||
* 6. OpenSSL
|
||||
* 7. libmd
|
||||
* 8. Windows API
|
||||
* 4. libmd
|
||||
* 5. libSystem
|
||||
* 6. Windows API
|
||||
* 7. mbedTLS
|
||||
* 8. Nettle
|
||||
* 9. OpenSSL
|
||||
*/
|
||||
const struct archive_digest __archive_digest =
|
||||
{
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM) ||\
|
||||
defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#define ARCHIVE_CRYPTO_CommonCrypto 1
|
||||
#endif
|
||||
|
||||
/* mbed TLS crypto headers */
|
||||
@@ -167,6 +168,7 @@
|
||||
#if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
/* don't use bcrypt when XP needs to be supported */
|
||||
#include <bcrypt.h>
|
||||
#define ARCHIVE_CRYPTO_CNG 1
|
||||
typedef struct {
|
||||
int valid;
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
@@ -175,6 +177,7 @@ typedef struct {
|
||||
#else
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#define ARCHIVE_CRYPTO_WINCRYPT 1
|
||||
typedef struct {
|
||||
int valid;
|
||||
HCRYPTPROV cryptProv;
|
||||
@@ -190,14 +193,16 @@ typedef MD5_CTX archive_md5_ctx;
|
||||
typedef MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_LIBSYSTEM)
|
||||
typedef CC_MD5_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
typedef Digest_CTX archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_md5_context archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct md5_ctx archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_md5_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_MD5_WIN)
|
||||
typedef Digest_CTX archive_md5_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_md5_ctx;
|
||||
#endif
|
||||
@@ -207,8 +212,10 @@ typedef RMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_LIBMD)
|
||||
typedef RIPEMD160_CTX archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_ripemd160_context archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct ripemd160_ctx archive_rmd160_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_RMD160_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_rmd160_ctx;
|
||||
@@ -222,14 +229,16 @@ typedef SHA1_CTX archive_sha1_ctx;
|
||||
typedef SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_LIBSYSTEM)
|
||||
typedef CC_SHA1_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
typedef Digest_CTX archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha1_context archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha1_ctx archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha1_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA1_WIN)
|
||||
typedef Digest_CTX archive_sha1_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha1_ctx;
|
||||
#endif
|
||||
@@ -244,14 +253,16 @@ typedef SHA2_CTX archive_sha256_ctx;
|
||||
typedef SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_LIBSYSTEM)
|
||||
typedef CC_SHA256_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
typedef Digest_CTX archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha256_context archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha256_ctx archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha256_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA256_WIN)
|
||||
typedef Digest_CTX archive_sha256_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha256_ctx;
|
||||
#endif
|
||||
@@ -264,14 +275,16 @@ typedef SHA384_CTX archive_sha384_ctx;
|
||||
typedef SHA2_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
typedef Digest_CTX archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha512_context archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha384_ctx archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha384_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA384_WIN)
|
||||
typedef Digest_CTX archive_sha384_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha384_ctx;
|
||||
#endif
|
||||
@@ -286,14 +299,16 @@ typedef SHA2_CTX archive_sha512_ctx;
|
||||
typedef SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_LIBSYSTEM)
|
||||
typedef CC_SHA512_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
typedef Digest_CTX archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_MBEDTLS)
|
||||
#define ARCHIVE_CRYPTO_MBED 1
|
||||
typedef mbedtls_sha512_context archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_NETTLE)
|
||||
#define ARCHIVE_CRYPTO_NETTLE 1
|
||||
typedef struct sha512_ctx archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_OPENSSL)
|
||||
typedef EVP_MD_CTX *archive_sha512_ctx;
|
||||
#elif defined(ARCHIVE_CRYPTO_SHA512_WIN)
|
||||
typedef Digest_CTX archive_sha512_ctx;
|
||||
#else
|
||||
typedef unsigned char archive_sha512_ctx;
|
||||
#endif
|
||||
|
||||
@@ -262,7 +262,7 @@ translate_acl(struct archive_read_disk *a,
|
||||
}
|
||||
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
|
||||
r = acl_get_flag_np(acl_flagset,
|
||||
acl_nfs4_flag_map[i].p_perm);
|
||||
(acl_flag_t)acl_nfs4_flag_map[i].p_perm);
|
||||
if (r == -1) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Failed to check flag in a NFSv4 "
|
||||
@@ -517,7 +517,7 @@ set_acl(struct archive *a, int fd, const char *name,
|
||||
for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
|
||||
if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
|
||||
if (acl_add_flag_np(acl_flagset,
|
||||
acl_nfs4_flag_map[i].p_perm) != 0) {
|
||||
(acl_flag_t)acl_nfs4_flag_map[i].p_perm) != 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to add flag to "
|
||||
"NFSv4 ACL flagset");
|
||||
|
||||
@@ -275,7 +275,7 @@ archive_entry_new2(struct archive *a)
|
||||
* Functions for reading fields from an archive_entry.
|
||||
*/
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_atime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_atime);
|
||||
@@ -293,7 +293,7 @@ archive_entry_atime_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_ATIME);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_birthtime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_birthtime);
|
||||
@@ -311,7 +311,7 @@ archive_entry_birthtime_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_BIRTHTIME);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_ctime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_ctime);
|
||||
@@ -329,7 +329,7 @@ archive_entry_ctime_nsec(struct archive_entry *entry)
|
||||
return (entry->ae_stat.aest_ctime_nsec);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_dev(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -345,7 +345,7 @@ archive_entry_dev_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_DEV);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_devmajor(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -354,7 +354,7 @@ archive_entry_devmajor(struct archive_entry *entry)
|
||||
return major(entry->ae_stat.aest_dev);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_devminor(struct archive_entry *entry)
|
||||
{
|
||||
if (entry->ae_stat.aest_dev_is_broken_down)
|
||||
@@ -568,7 +568,7 @@ archive_entry_mode(struct archive_entry *entry)
|
||||
return (entry->acl.mode);
|
||||
}
|
||||
|
||||
time_t
|
||||
__LA_TIME_T
|
||||
archive_entry_mtime(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_stat.aest_mtime);
|
||||
@@ -667,7 +667,7 @@ archive_entry_rdev_is_set(struct archive_entry *entry)
|
||||
return (entry->ae_set & AE_SET_RDEV);
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdev(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -681,7 +681,7 @@ archive_entry_rdev(struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdevmajor(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -694,7 +694,7 @@ archive_entry_rdevmajor(struct archive_entry *entry)
|
||||
}
|
||||
}
|
||||
|
||||
dev_t
|
||||
__LA_DEV_T
|
||||
archive_entry_rdevminor(struct archive_entry *entry)
|
||||
{
|
||||
if (archive_entry_rdev_is_set(entry)) {
|
||||
@@ -984,7 +984,9 @@ void
|
||||
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
|
||||
{
|
||||
if (ino < 0) {
|
||||
ino = 0;
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set &= ~AE_SET_INO;
|
||||
return;
|
||||
}
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_INO;
|
||||
@@ -995,7 +997,9 @@ void
|
||||
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
|
||||
{
|
||||
if (ino < 0) {
|
||||
ino = 0;
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set &= ~AE_SET_INO;
|
||||
return;
|
||||
}
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_INO;
|
||||
@@ -1088,7 +1092,7 @@ _archive_entry_copy_hardlink_l(struct archive_entry *entry,
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_atime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_atime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1105,7 +1109,7 @@ archive_entry_unset_atime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_birthtime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_birthtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1122,7 +1126,7 @@ archive_entry_unset_birthtime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_ctime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_ctime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1139,7 +1143,7 @@ archive_entry_unset_ctime(struct archive_entry *entry)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_dev(struct archive_entry *entry, dev_t d)
|
||||
archive_entry_set_dev(struct archive_entry *entry, __LA_DEV_T d)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1148,7 +1152,7 @@ archive_entry_set_dev(struct archive_entry *entry, dev_t d)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_devmajor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1157,7 +1161,7 @@ archive_entry_set_devmajor(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_devminor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_devminor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_set |= AE_SET_DEV;
|
||||
@@ -1243,7 +1247,7 @@ archive_entry_set_mode(struct archive_entry *entry, mode_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_mtime(struct archive_entry *entry, time_t t, long ns)
|
||||
archive_entry_set_mtime(struct archive_entry *entry, __LA_TIME_T t, long ns)
|
||||
{
|
||||
FIX_NS(t, ns);
|
||||
entry->stat_valid = 0;
|
||||
@@ -1319,7 +1323,7 @@ archive_entry_set_perm(struct archive_entry *entry, mode_t p)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdev(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev = m;
|
||||
@@ -1330,7 +1334,7 @@ archive_entry_set_rdev(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdevmajor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev_is_broken_down = 1;
|
||||
@@ -1340,7 +1344,7 @@ archive_entry_set_rdevmajor(struct archive_entry *entry, dev_t m)
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_rdevminor(struct archive_entry *entry, dev_t m)
|
||||
archive_entry_set_rdevminor(struct archive_entry *entry, __LA_DEV_T m)
|
||||
{
|
||||
entry->stat_valid = 0;
|
||||
entry->ae_stat.aest_rdev_is_broken_down = 1;
|
||||
@@ -1603,21 +1607,27 @@ archive_entry_set_digest(struct archive_entry *entry, int type,
|
||||
switch (type) {
|
||||
case ARCHIVE_ENTRY_DIGEST_MD5:
|
||||
copy_digest(entry, md5, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_MD5;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_RMD160:
|
||||
copy_digest(entry, rmd160, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_RMD160;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA1:
|
||||
copy_digest(entry, sha1, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA1;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA256:
|
||||
copy_digest(entry, sha256, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA256;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA384:
|
||||
copy_digest(entry, sha384, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA384;
|
||||
break;
|
||||
case ARCHIVE_ENTRY_DIGEST_SHA512:
|
||||
copy_digest(entry, sha512, digest);
|
||||
entry->mset_digest |= AE_MSET_DIGEST_SHA512;
|
||||
break;
|
||||
default:
|
||||
return ARCHIVE_WARN;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3007007
|
||||
#define ARCHIVE_VERSION_NUMBER 3008001
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
@@ -40,8 +40,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdint.h>
|
||||
#include <stdint.h> /* for C99 int64_t, etc. */
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* time_t is slated to be removed from public includes in 4.0 */
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
@@ -55,12 +58,15 @@
|
||||
#define __LA_INT64_T_DEFINED
|
||||
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
|
||||
typedef __int64 la_int64_t;
|
||||
typedef unsigned __int64 la_uint64_t;
|
||||
# else
|
||||
#include <unistd.h>
|
||||
# if defined(_SCO_DS) || defined(__osf__)
|
||||
typedef long long la_int64_t;
|
||||
typedef unsigned long long la_uint64_t;
|
||||
# else
|
||||
typedef int64_t la_int64_t;
|
||||
typedef uint64_t la_uint64_t;
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
@@ -96,6 +102,30 @@ typedef ssize_t la_ssize_t;
|
||||
# define __LA_MODE_T mode_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for time_t */
|
||||
#define __LA_TIME_T time_t
|
||||
#else
|
||||
/* Use 64-bits integer types for time_t */
|
||||
#define __LA_TIME_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Use the platform types for dev_t */
|
||||
#define __LA_DEV_T dev_t
|
||||
#else
|
||||
/* Use 64-bits integer types for dev_t */
|
||||
#define __LA_DEV_T la_int64_t
|
||||
#endif
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
/* Libarchive 3.x used signed int64 for inode numbers */
|
||||
#define __LA_INO_T la_int64_t
|
||||
#else
|
||||
/* Switch to unsigned for libarchive 4.0 */
|
||||
#define __LA_INO_T la_uint64_t
|
||||
#endif
|
||||
|
||||
/* Large file support for Android */
|
||||
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
|
||||
#include "android_lf.h"
|
||||
@@ -127,7 +157,8 @@ typedef ssize_t la_ssize_t;
|
||||
# define __LA_DECL
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
|
||||
#if defined(__GNUC__) && (__GNUC__ > 3 || \
|
||||
(__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
# define __LA_DEPRECATED __attribute__((deprecated))
|
||||
#else
|
||||
# define __LA_DEPRECATED
|
||||
@@ -235,19 +266,19 @@ __LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
|
||||
* also return NULL when implicit character set conversions fail.
|
||||
* This is usually what you want.
|
||||
*/
|
||||
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_atime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_birthtime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL __LA_TIME_T archive_entry_ctime(struct archive_entry *);
|
||||
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_dev(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_devmajor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_devminor(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_filetype_is_set(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_fflags(struct archive_entry *,
|
||||
@@ -264,8 +295,8 @@ __LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_hardlink_is_set(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL __LA_INO_T archive_entry_ino(struct archive_entry *);
|
||||
__LA_DECL __LA_INO_T archive_entry_ino64(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
|
||||
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
|
||||
@@ -278,9 +309,9 @@ __LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
|
||||
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_perm_is_set(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_rdev_is_set(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdev(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdevmajor(struct archive_entry *);
|
||||
__LA_DECL __LA_DEV_T archive_entry_rdevminor(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
|
||||
@@ -309,18 +340,18 @@ __LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
|
||||
* always copied.
|
||||
*/
|
||||
|
||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_atime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
|
||||
#endif
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_dev(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
|
||||
unsigned long /* set */, unsigned long /* clear */);
|
||||
@@ -343,15 +374,15 @@ __LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const cha
|
||||
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_set_ino(struct archive_entry *, __LA_INO_T);
|
||||
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, __LA_INO_T);
|
||||
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
|
||||
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, __LA_TIME_T, long);
|
||||
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
|
||||
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
|
||||
@@ -360,9 +391,9 @@ __LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *)
|
||||
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
|
||||
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, __LA_DEV_T);
|
||||
__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
|
||||
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
|
||||
@@ -418,6 +449,7 @@ __LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const voi
|
||||
#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006
|
||||
|
||||
__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
|
||||
__LA_DECL int archive_entry_set_digest(struct archive_entry *, int, const unsigned char *);
|
||||
|
||||
/*
|
||||
* ACL routines. This used to simply store and return text-format ACL
|
||||
|
||||
@@ -280,6 +280,10 @@ find_entry(struct archive_entry_linkresolver *res,
|
||||
dev_t dev;
|
||||
int64_t ino;
|
||||
|
||||
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Free a held entry. */
|
||||
if (res->spare != NULL) {
|
||||
archive_entry_free(res->spare->canonical);
|
||||
@@ -369,6 +373,10 @@ insert_entry(struct archive_entry_linkresolver *res,
|
||||
struct links_entry *le;
|
||||
size_t hash, bucket;
|
||||
|
||||
if (!archive_entry_ino_is_set(entry) || !archive_entry_dev_is_set(entry)) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Add this entry to the links cache. */
|
||||
le = calloc(1, sizeof(struct links_entry));
|
||||
if (le == NULL)
|
||||
|
||||
@@ -87,4 +87,4 @@ int _archive_entry_copy_symlink_l(struct archive_entry *,
|
||||
int _archive_entry_copy_uname_l(struct archive_entry *,
|
||||
const char *, size_t, struct archive_string_conv *);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ENTRY_LOCALE_H_INCLUDED */
|
||||
@@ -174,6 +174,13 @@ struct archive_entry {
|
||||
size_t mac_metadata_size;
|
||||
|
||||
/* Digest support. */
|
||||
#define AE_MSET_DIGEST_MD5 1
|
||||
#define AE_MSET_DIGEST_RMD160 2
|
||||
#define AE_MSET_DIGEST_SHA1 4
|
||||
#define AE_MSET_DIGEST_SHA256 8
|
||||
#define AE_MSET_DIGEST_SHA384 16
|
||||
#define AE_MSET_DIGEST_SHA512 32
|
||||
uint_least32_t mset_digest;
|
||||
struct ae_digest digest;
|
||||
|
||||
/* ACL support. */
|
||||
@@ -195,8 +202,4 @@ struct archive_entry {
|
||||
int ae_symlink_type;
|
||||
};
|
||||
|
||||
int
|
||||
archive_entry_set_digest(struct archive_entry *entry, int type,
|
||||
const unsigned char *digest);
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
@@ -116,4 +116,4 @@ struct archive_hmac {
|
||||
};
|
||||
|
||||
extern const struct archive_hmac __archive_hmac;
|
||||
#endif /* ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_HMAC_PRIVATE_H_INCLUDED */
|
||||
@@ -35,14 +35,17 @@
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_getdate.h"
|
||||
#include "archive_pathmatch.h"
|
||||
#include "archive_rb.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_time_private.h"
|
||||
|
||||
struct match {
|
||||
struct match *next;
|
||||
@@ -53,8 +56,7 @@ struct match {
|
||||
struct match_list {
|
||||
struct match *first;
|
||||
struct match **last;
|
||||
int count;
|
||||
int unmatched_count;
|
||||
size_t unmatched_count;
|
||||
struct match *unmatched_next;
|
||||
int unmatched_eof;
|
||||
};
|
||||
@@ -73,7 +75,6 @@ struct match_file {
|
||||
struct entry_list {
|
||||
struct match_file *first;
|
||||
struct match_file **last;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct id_array {
|
||||
@@ -144,12 +145,15 @@ static int add_pattern_mbs(struct archive_match *, struct match_list *,
|
||||
const char *);
|
||||
static int add_pattern_wcs(struct archive_match *, struct match_list *,
|
||||
const wchar_t *);
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
static int cmp_key_mbs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_node_mbs(const struct archive_rb_node *,
|
||||
const struct archive_rb_node *);
|
||||
#else
|
||||
static int cmp_key_wcs(const struct archive_rb_node *, const void *);
|
||||
static int cmp_node_wcs(const struct archive_rb_node *,
|
||||
const struct archive_rb_node *);
|
||||
#endif
|
||||
static void entry_list_add(struct entry_list *, struct match_file *);
|
||||
static void entry_list_free(struct entry_list *);
|
||||
static void entry_list_init(struct entry_list *);
|
||||
@@ -187,14 +191,14 @@ static int time_excluded(struct archive_match *,
|
||||
struct archive_entry *);
|
||||
static int validate_time_flag(struct archive *, int, const char *);
|
||||
|
||||
#define get_date __archive_get_date
|
||||
#define get_date archive_parse_date
|
||||
|
||||
static const struct archive_rb_tree_ops rb_ops_mbs = {
|
||||
static const struct archive_rb_tree_ops rb_ops = {
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
cmp_node_mbs, cmp_key_mbs
|
||||
};
|
||||
|
||||
static const struct archive_rb_tree_ops rb_ops_wcs = {
|
||||
#else
|
||||
cmp_node_wcs, cmp_key_wcs
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -228,7 +232,7 @@ archive_match_new(void)
|
||||
a->recursive_include = 1;
|
||||
match_list_init(&(a->inclusions));
|
||||
match_list_init(&(a->exclusions));
|
||||
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
|
||||
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops);
|
||||
entry_list_init(&(a->exclusion_entry_list));
|
||||
match_list_init(&(a->inclusion_unames));
|
||||
match_list_init(&(a->inclusion_gnames));
|
||||
@@ -507,7 +511,9 @@ archive_match_path_unmatched_inclusions(struct archive *_a)
|
||||
ARCHIVE_STATE_NEW, "archive_match_unmatched_inclusions");
|
||||
a = (struct archive_match *)_a;
|
||||
|
||||
return (a->inclusions.unmatched_count);
|
||||
if (a->inclusions.unmatched_count > (size_t)INT_MAX)
|
||||
return INT_MAX;
|
||||
return (int)(a->inclusions.unmatched_count);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -650,7 +656,7 @@ add_pattern_from_file(struct archive_match *a, struct match_list *mlist,
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (*b == 0x0d || *b == 0x0a) {
|
||||
if (*b == 0x0d || *b == 0x0a) {
|
||||
found_separator = 1;
|
||||
break;
|
||||
}
|
||||
@@ -735,7 +741,7 @@ path_excluded(struct archive_match *a, int mbs, const void *pathname)
|
||||
}
|
||||
}
|
||||
|
||||
/* Exclusions take priority */
|
||||
/* Exclusions take priority. */
|
||||
for (match = a->exclusions.first; match != NULL;
|
||||
match = match->next){
|
||||
r = match_path_exclusion(a, match, mbs, pathname);
|
||||
@@ -834,7 +840,6 @@ match_list_init(struct match_list *list)
|
||||
{
|
||||
list->first = NULL;
|
||||
list->last = &(list->first);
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -855,7 +860,6 @@ match_list_add(struct match_list *list, struct match *m)
|
||||
{
|
||||
*list->last = m;
|
||||
list->last = &(m->next);
|
||||
list->count++;
|
||||
list->unmatched_count++;
|
||||
}
|
||||
|
||||
@@ -1145,36 +1149,15 @@ set_timefilter_date_w(struct archive_match *a, int timetype,
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
static int
|
||||
set_timefilter_find_data(struct archive_match *a, int timetype,
|
||||
DWORD ftLastWriteTime_dwHighDateTime, DWORD ftLastWriteTime_dwLowDateTime,
|
||||
DWORD ftCreationTime_dwHighDateTime, DWORD ftCreationTime_dwLowDateTime)
|
||||
const FILETIME* ftLastWriteTime, const FILETIME* ftCreationTime)
|
||||
{
|
||||
ULARGE_INTEGER utc;
|
||||
time_t ctime_sec, mtime_sec;
|
||||
long ctime_ns, mtime_ns;
|
||||
uint32_t ctime_ns, mtime_ns;
|
||||
|
||||
utc.HighPart = ftCreationTime_dwHighDateTime;
|
||||
utc.LowPart = ftCreationTime_dwLowDateTime;
|
||||
if (utc.QuadPart >= EPOC_TIME) {
|
||||
utc.QuadPart -= EPOC_TIME;
|
||||
ctime_sec = (time_t)(utc.QuadPart / 10000000);
|
||||
ctime_ns = (long)(utc.QuadPart % 10000000) * 100;
|
||||
} else {
|
||||
ctime_sec = 0;
|
||||
ctime_ns = 0;
|
||||
}
|
||||
utc.HighPart = ftLastWriteTime_dwHighDateTime;
|
||||
utc.LowPart = ftLastWriteTime_dwLowDateTime;
|
||||
if (utc.QuadPart >= EPOC_TIME) {
|
||||
utc.QuadPart -= EPOC_TIME;
|
||||
mtime_sec = (time_t)(utc.QuadPart / 10000000);
|
||||
mtime_ns = (long)(utc.QuadPart % 10000000) * 100;
|
||||
} else {
|
||||
mtime_sec = 0;
|
||||
mtime_ns = 0;
|
||||
}
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftLastWriteTime), &mtime_sec, &mtime_ns);
|
||||
ntfs_to_unix(FILETIME_to_ntfs(ftCreationTime), &ctime_sec, &ctime_ns);
|
||||
return set_timefilter(a, timetype,
|
||||
mtime_sec, mtime_ns, ctime_sec, ctime_ns);
|
||||
}
|
||||
@@ -1199,9 +1182,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
FindClose(h);
|
||||
return set_timefilter_find_data(a, timetype,
|
||||
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
|
||||
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
|
||||
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1223,9 +1204,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
FindClose(h);
|
||||
return set_timefilter_find_data(a, timetype,
|
||||
d.ftLastWriteTime.dwHighDateTime, d.ftLastWriteTime.dwLowDateTime,
|
||||
d.ftCreationTime.dwHighDateTime, d.ftCreationTime.dwLowDateTime);
|
||||
return set_timefilter_find_data(a, timetype, &d.ftLastWriteTime, &d.ftCreationTime);
|
||||
}
|
||||
|
||||
#else /* _WIN32 && !__CYGWIN__ */
|
||||
@@ -1300,6 +1279,7 @@ set_timefilter_pathname_wcs(struct archive_match *a, int timetype,
|
||||
/*
|
||||
* Call back functions for archive_rb.
|
||||
*/
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
static int
|
||||
cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
@@ -1316,7 +1296,7 @@ cmp_node_mbs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (strcmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_mbs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -1328,7 +1308,7 @@ cmp_key_mbs(const struct archive_rb_node *n, const void *key)
|
||||
return (-1);
|
||||
return (strcmp(p, (const char *)key));
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
cmp_node_wcs(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
@@ -1345,7 +1325,7 @@ cmp_node_wcs(const struct archive_rb_node *n1,
|
||||
return (-1);
|
||||
return (wcscmp(p1, p2));
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cmp_key_wcs(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
@@ -1357,13 +1337,13 @@ cmp_key_wcs(const struct archive_rb_node *n, const void *key)
|
||||
return (-1);
|
||||
return (wcscmp(p, (const wchar_t *)key));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
entry_list_init(struct entry_list *list)
|
||||
{
|
||||
list->first = NULL;
|
||||
list->last = &(list->first);
|
||||
list->count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1384,7 +1364,6 @@ entry_list_add(struct entry_list *list, struct match_file *file)
|
||||
{
|
||||
*list->last = file;
|
||||
list->last = &(file->next);
|
||||
list->count++;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1407,9 +1386,7 @@ add_entry(struct archive_match *a, int flag,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_mstring_copy_wcs(&(f->pathname), pathname);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
if (pathname == NULL) {
|
||||
free(f);
|
||||
@@ -1417,7 +1394,6 @@ add_entry(struct archive_match *a, int flag,
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
archive_mstring_copy_mbs(&(f->pathname), pathname);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
|
||||
#endif
|
||||
f->flag = flag;
|
||||
f->mtime_sec = archive_entry_mtime(entry);
|
||||
@@ -1542,16 +1518,13 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
}
|
||||
|
||||
/* If there is no exclusion list, include the file. */
|
||||
if (a->exclusion_entry_list.count == 0)
|
||||
if (a->exclusion_entry_list.first == NULL)
|
||||
return (0);
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
pathname = archive_entry_pathname_w(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_wcs;
|
||||
#else
|
||||
(void)rb_ops_wcs;
|
||||
pathname = archive_entry_pathname(entry);
|
||||
a->exclusion_tree.rbt_ops = &rb_ops_mbs;
|
||||
#endif
|
||||
if (pathname == NULL)
|
||||
return (0);
|
||||
@@ -1707,7 +1680,7 @@ archive_match_owner_excluded(struct archive *_a,
|
||||
static int
|
||||
add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
{
|
||||
unsigned i;
|
||||
size_t i;
|
||||
|
||||
if (ids->count + 1 >= ids->size) {
|
||||
void *p;
|
||||
@@ -1744,10 +1717,10 @@ add_owner_id(struct archive_match *a, struct id_array *ids, int64_t id)
|
||||
static int
|
||||
match_owner_id(struct id_array *ids, int64_t id)
|
||||
{
|
||||
unsigned b, m, t;
|
||||
size_t b, m, t;
|
||||
|
||||
t = 0;
|
||||
b = (unsigned)ids->count;
|
||||
b = ids->count;
|
||||
while (t < b) {
|
||||
m = (t + b)>>1;
|
||||
if (ids->ids[m] == id)
|
||||
@@ -1842,7 +1815,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (a->inclusion_unames.count) {
|
||||
if (a->inclusion_unames.first != NULL) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
r = match_owner_name_wcs(a, &(a->inclusion_unames),
|
||||
archive_entry_uname_w(entry));
|
||||
@@ -1856,7 +1829,7 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
return (r);
|
||||
}
|
||||
|
||||
if (a->inclusion_gnames.count) {
|
||||
if (a->inclusion_gnames.first != NULL) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
r = match_owner_name_wcs(a, &(a->inclusion_gnames),
|
||||
archive_entry_gname_w(entry));
|
||||
@@ -1871,4 +1844,3 @@ owner_excluded(struct archive_match *a, struct archive_entry *entry)
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ parse_option(const char **str,
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *m, const char *o, const char *v,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
unsigned int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
const char *mp, *op, *vp;
|
||||
int r;
|
||||
@@ -97,7 +97,7 @@ _archive_set_either_option(struct archive *a, const char *m, const char *o, cons
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option)
|
||||
unsigned int magic, const char *fn, option_handler use_option)
|
||||
{
|
||||
int allok = 1, anyok = 0, ignore_mod_err = 0, r;
|
||||
char *data;
|
||||
|
||||
@@ -35,11 +35,11 @@ typedef int (*option_handler)(struct archive *a,
|
||||
int
|
||||
_archive_set_option(struct archive *a,
|
||||
const char *mod, const char *opt, const char *val,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
unsigned int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_options(struct archive *a, const char *options,
|
||||
int magic, const char *fn, option_handler use_option);
|
||||
unsigned int magic, const char *fn, option_handler use_option);
|
||||
|
||||
int
|
||||
_archive_set_either_option(struct archive *a,
|
||||
|
||||
@@ -46,4 +46,4 @@ pack_t pack_native;
|
||||
(((y) << 12) & 0xfff00000) | \
|
||||
(((y) << 0) & 0x000000ff)))
|
||||
|
||||
#endif /* ARCHIVE_PACK_DEV_H */
|
||||
#endif /* !ARCHIVE_PACK_DEV_H */
|
||||
+56
-9
@@ -35,8 +35,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define __LIBARCHIVE_BUILD 1
|
||||
#include "archive_getdate.h"
|
||||
#include "archive.h"
|
||||
|
||||
/* Basic time units. */
|
||||
#define EPOCH 1970
|
||||
@@ -820,6 +819,23 @@ RelativeMonth(time_t Start, time_t Timezone, time_t RelMonth)
|
||||
Timezone, DSTmaybe));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses and consumes an unsigned number.
|
||||
* Returns 1 if any number is parsed. Otherwise, *value is unchanged.
|
||||
*/
|
||||
static char
|
||||
consume_unsigned_number(const char **in, time_t *value)
|
||||
{
|
||||
char c;
|
||||
if (isdigit((unsigned char)(c = **in))) {
|
||||
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
|
||||
*value = 10 * *value + c - '0';
|
||||
(*in)--;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tokenizer.
|
||||
*/
|
||||
@@ -861,7 +877,8 @@ nexttoken(const char **in, time_t *value)
|
||||
&& i < sizeof(buff)-1) {
|
||||
if (*src != '.') {
|
||||
if (isupper((unsigned char)*src))
|
||||
buff[i++] = tolower((unsigned char)*src);
|
||||
buff[i++] = (char)tolower(
|
||||
(unsigned char)*src);
|
||||
else
|
||||
buff[i++] = *src;
|
||||
}
|
||||
@@ -895,10 +912,7 @@ nexttoken(const char **in, time_t *value)
|
||||
* Because '-' and '+' have other special meanings, I
|
||||
* don't deal with signed numbers here.
|
||||
*/
|
||||
if (isdigit((unsigned char)(c = **in))) {
|
||||
for (*value = 0; isdigit((unsigned char)(c = *(*in)++)); )
|
||||
*value = 10 * *value + c - '0';
|
||||
(*in)--;
|
||||
if (consume_unsigned_number(in, value)) {
|
||||
return (tUNUMBER);
|
||||
}
|
||||
|
||||
@@ -914,7 +928,7 @@ difftm (struct tm *a, struct tm *b)
|
||||
{
|
||||
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||
int days = (
|
||||
long days = (
|
||||
/* difference in day of year */
|
||||
a->tm_yday - b->tm_yday
|
||||
/* + intervening leap days */
|
||||
@@ -929,6 +943,32 @@ difftm (struct tm *a, struct tm *b)
|
||||
+ (a->tm_sec - b->tm_sec));
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses a Unix epoch timestamp (seconds).
|
||||
* This supports a subset of what GNU tar accepts from black box testing,
|
||||
* but covers common use cases.
|
||||
*/
|
||||
static time_t
|
||||
parse_unix_epoch(const char *p)
|
||||
{
|
||||
time_t epoch;
|
||||
|
||||
/* may begin with + */
|
||||
if (*p == '+') {
|
||||
p++;
|
||||
}
|
||||
|
||||
/* followed by some number */
|
||||
if (!consume_unsigned_number(&p, &epoch))
|
||||
return (time_t)-1;
|
||||
|
||||
/* ...and nothing else */
|
||||
if (*p != '\0')
|
||||
return (time_t)-1;
|
||||
|
||||
return epoch;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* The public function.
|
||||
@@ -936,7 +976,7 @@ difftm (struct tm *a, struct tm *b)
|
||||
* TODO: tokens[] array should be dynamically sized.
|
||||
*/
|
||||
time_t
|
||||
__archive_get_date(time_t now, const char *p)
|
||||
archive_parse_date(time_t now, const char *p)
|
||||
{
|
||||
struct token tokens[256];
|
||||
struct gdstate _gds;
|
||||
@@ -948,6 +988,13 @@ __archive_get_date(time_t now, const char *p)
|
||||
time_t tod;
|
||||
long tzone;
|
||||
|
||||
/*
|
||||
* @-prefixed Unix epoch timestamps (seconds)
|
||||
* Skip the complex tokenizer - We do not want to accept strings like "@tenth"
|
||||
*/
|
||||
if (*p == '@')
|
||||
return parse_unix_epoch(p + 1);
|
||||
|
||||
/* Clear out the parsed token array. */
|
||||
memset(tokens, 0, sizeof(tokens));
|
||||
/* Initialize the parser state. */
|
||||
@@ -61,6 +61,11 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* For cygwin, to avoid missing LONG, ULONG, PUCHAR, ... definitions */
|
||||
#ifdef __CYGWIN__
|
||||
#include <windef.h>
|
||||
#endif
|
||||
|
||||
/* It should be possible to get rid of this by extending the feature-test
|
||||
* macros to cover Windows API functions, probably along with non-trivial
|
||||
* refactoring of code to find structures that sit more cleanly on top of
|
||||
|
||||
@@ -50,4 +50,4 @@
|
||||
#define ARCHIVE_ACL_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_ACL_H_INCLUDED */
|
||||
@@ -42,4 +42,4 @@
|
||||
#define ARCHIVE_XATTR_SUPPORT 1
|
||||
#endif
|
||||
|
||||
#endif /* ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_PLATFORM_XATTR_H_INCLUDED */
|
||||
@@ -287,9 +287,14 @@ static void *AllocUnits(CPpmd7 *p, unsigned indx)
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *s = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; } while(--n); }
|
||||
#define MyMem12Cpy(dest, src, num) do { \
|
||||
UInt32 *d = (UInt32 *)dest; \
|
||||
const UInt32 *s = (const UInt32 *)src; \
|
||||
UInt32 n = num; \
|
||||
do { \
|
||||
d[0] = s[0]; d[1] = s[1]; d[2] = s[2]; s += 3; d += 3; \
|
||||
} while(--n); \
|
||||
} while (0)
|
||||
|
||||
static void *ShrinkUnits(CPpmd7 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
|
||||
@@ -242,9 +242,14 @@ static void *AllocUnits(CPpmd8 *p, unsigned indx)
|
||||
return AllocUnitsRare(p, indx);
|
||||
}
|
||||
|
||||
#define MyMem12Cpy(dest, src, num) \
|
||||
{ UInt32 *d = (UInt32 *)dest; const UInt32 *z = (const UInt32 *)src; UInt32 n = num; \
|
||||
do { d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; } while (--n); }
|
||||
#define MyMem12Cpy(dest, src, num) do { \
|
||||
UInt32 *d = (UInt32 *)dest; \
|
||||
const UInt32 *z = (const UInt32 *)src; \
|
||||
UInt32 n = num; \
|
||||
do { \
|
||||
d[0] = z[0]; d[1] = z[1]; d[2] = z[2]; z += 3; d += 3; \
|
||||
} while (--n); \
|
||||
} while (0)
|
||||
|
||||
static void *ShrinkUnits(CPpmd8 *p, void *oldPtr, unsigned oldNU, unsigned newNU)
|
||||
{
|
||||
@@ -341,7 +346,9 @@ static void SetSuccessor(CPpmd_State *p, CPpmd_Void_Ref v)
|
||||
(p)->SuccessorHigh = (UInt16)(((UInt32)(v) >> 16) & 0xFFFF);
|
||||
}
|
||||
|
||||
#define RESET_TEXT(offs) { p->Text = p->Base + p->AlignOffset + (offs); }
|
||||
#define RESET_TEXT(offs) do { \
|
||||
p->Text = p->Base + p->AlignOffset + (offs); \
|
||||
} while (0)
|
||||
|
||||
static void RestartModel(CPpmd8 *p)
|
||||
{
|
||||
|
||||
@@ -109,8 +109,12 @@ typedef struct
|
||||
Byte Count; /* Count to next change of Shift */
|
||||
} CPpmd_See;
|
||||
|
||||
#define Ppmd_See_Update(p) if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) \
|
||||
{ (p)->Summ <<= 1; (p)->Count = (Byte)(3 << (p)->Shift++); }
|
||||
#define Ppmd_See_Update(p) do { \
|
||||
if ((p)->Shift < PPMD_PERIOD_BITS && --(p)->Count == 0) { \
|
||||
(p)->Summ <<= 1; \
|
||||
(p)->Count = (Byte)(3 << (p)->Shift++); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -144,8 +148,12 @@ typedef
|
||||
#endif
|
||||
CPpmd_Byte_Ref;
|
||||
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) \
|
||||
{ unsigned j; for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
|
||||
p[j+7] = p[j+6] = p[j+5] = p[j+4] = p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; }}
|
||||
#define PPMD_SetAllBitsIn256Bytes(p) do { \
|
||||
unsigned j; \
|
||||
for (j = 0; j < 256 / sizeof(p[0]); j += 8) { \
|
||||
p[j+7] = p[j+6] = p[j+5] = p[j+4] = \
|
||||
p[j+3] = p[j+2] = p[j+1] = p[j+0] = ~(size_t)0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
@@ -33,4 +33,4 @@
|
||||
/* Random number generator. */
|
||||
int archive_random(void *buf, size_t nbytes);
|
||||
|
||||
#endif /* ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
|
||||
#endif /* !ARCHIVE_RANDOM_PRIVATE_H_INCLUDED */
|
||||
@@ -110,4 +110,4 @@ struct archive_rb_node *
|
||||
__archive_rb_tree_iterate(struct archive_rb_tree *,
|
||||
struct archive_rb_node *, const unsigned int);
|
||||
|
||||
#endif /* ARCHIVE_RB_H_*/
|
||||
#endif /* !ARCHIVE_RB_H_INCLUDED */
|
||||
@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
|
||||
return 0;
|
||||
|
||||
if (self->archive->client.skipper != NULL) {
|
||||
/* Seek requests over 1GiB are broken down into
|
||||
* multiple seeks. This avoids overflows when the
|
||||
* requests get passed through 32-bit arguments. */
|
||||
int64_t skip_limit = (int64_t)1 << 30;
|
||||
int64_t total = 0;
|
||||
for (;;) {
|
||||
int64_t get, ask = request;
|
||||
if (ask > skip_limit)
|
||||
ask = skip_limit;
|
||||
get = (self->archive->client.skipper)
|
||||
(&self->archive->archive, self->data, ask);
|
||||
total += get;
|
||||
|
||||
@@ -96,6 +96,10 @@ archive_read_append_filter(struct archive *_a, int code)
|
||||
strcpy(str, "lzip");
|
||||
r1 = archive_read_support_filter_lzip(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZOP:
|
||||
strcpy(str, "lzop");
|
||||
r1 = archive_read_support_filter_lzop(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
strcpy(str, "lrzip");
|
||||
r1 = archive_read_support_filter_lrzip(_a);
|
||||
|
||||
@@ -888,7 +888,7 @@ setup_sparse_fiemap(struct archive_read_disk *a,
|
||||
count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
|
||||
fm = (struct fiemap *)buff;
|
||||
fm->fm_start = 0;
|
||||
fm->fm_length = ~0ULL;;
|
||||
fm->fm_length = ~0ULL;
|
||||
fm->fm_flags = FIEMAP_FLAG_SYNC;
|
||||
fm->fm_extent_count = count;
|
||||
do_fiemap = 1;
|
||||
|
||||
@@ -276,7 +276,7 @@ tree_dir_next_posix(struct tree *t);
|
||||
#endif
|
||||
|
||||
/* Initiate/terminate a tree traversal. */
|
||||
static struct tree *tree_open(const char *, int, int);
|
||||
static struct tree *tree_open(const char *, char, int);
|
||||
static struct tree *tree_reopen(struct tree *, const char *, int);
|
||||
static void tree_close(struct tree *);
|
||||
static void tree_free(struct tree *);
|
||||
@@ -514,7 +514,7 @@ _archive_read_close(struct archive *_a)
|
||||
|
||||
static void
|
||||
setup_symlink_mode(struct archive_read_disk *a, char symlink_mode,
|
||||
int follow_symlinks)
|
||||
char follow_symlinks)
|
||||
{
|
||||
a->symlink_mode = symlink_mode;
|
||||
a->follow_symlinks = follow_symlinks;
|
||||
@@ -778,7 +778,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
||||
*/
|
||||
if (t->current_sparse->offset > t->entry_total) {
|
||||
if (lseek(t->entry_fd,
|
||||
(off_t)t->current_sparse->offset, SEEK_SET) < 0) {
|
||||
(off_t)t->current_sparse->offset, SEEK_SET) !=
|
||||
t->current_sparse->offset) {
|
||||
archive_set_error(&a->archive, errno, "Seek error");
|
||||
r = ARCHIVE_FATAL;
|
||||
a->archive.state = ARCHIVE_STATE_FATAL;
|
||||
@@ -2180,7 +2181,7 @@ tree_append(struct tree *t, const char *name, size_t name_length)
|
||||
* Open a directory tree for traversal.
|
||||
*/
|
||||
static struct tree *
|
||||
tree_open(const char *path, int symlink_mode, int restore_time)
|
||||
tree_open(const char *path, char symlink_mode, int restore_time)
|
||||
{
|
||||
struct tree *t;
|
||||
|
||||
|
||||
@@ -52,10 +52,11 @@ struct archive_read_disk {
|
||||
|
||||
/*
|
||||
* Since symlink interaction changes, we need to track whether
|
||||
* we're following symlinks for the current item. 'L' mode above
|
||||
* sets this true, 'P' sets it false, 'H' changes it as we traverse.
|
||||
* we're following symlinks for the current item, governed by the above
|
||||
* symlink_mode. 'L' sets this true, 'P' sets it false, 'H' changes it
|
||||
* as we traverse.
|
||||
*/
|
||||
char follow_symlinks; /* Either 'L' or 'P'. */
|
||||
char follow_symlinks; /* Either 0 or 1. */
|
||||
|
||||
/* Directory traversals. */
|
||||
struct tree *tree;
|
||||
|
||||
@@ -37,8 +37,10 @@
|
||||
.Nm archive_read_support_format_lha ,
|
||||
.Nm archive_read_support_format_mtree ,
|
||||
.Nm archive_read_support_format_rar ,
|
||||
.Nm archive_read_support_format_rar5 ,
|
||||
.Nm archive_read_support_format_raw ,
|
||||
.Nm archive_read_support_format_tar ,
|
||||
.Nm archive_read_support_format_warc ,
|
||||
.Nm archive_read_support_format_xar ,
|
||||
.Nm archive_read_support_format_zip
|
||||
.Nd functions for reading streaming archives
|
||||
@@ -70,10 +72,14 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_rar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_rar5 "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_raw "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_tar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_warc "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_xar "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_format_zip "struct archive *"
|
||||
@@ -89,8 +95,10 @@ Streaming Archive Library (libarchive, -larchive)
|
||||
.Fn archive_read_support_format_lha ,
|
||||
.Fn archive_read_support_format_mtree ,
|
||||
.Fn archive_read_support_format_rar ,
|
||||
.Fn archive_read_support_format_rar5 ,
|
||||
.Fn archive_read_support_format_raw ,
|
||||
.Fn archive_read_support_format_tar ,
|
||||
.Fn archive_read_support_format_warc ,
|
||||
.Fn archive_read_support_format_xar ,
|
||||
.Fn archive_read_support_format_zip
|
||||
.Xc
|
||||
@@ -100,6 +108,13 @@ For example,
|
||||
.Fn archive_read_support_format_tar
|
||||
enables support for a variety of standard tar formats, old-style tar,
|
||||
ustar, pax interchange format, and many common variants.
|
||||
.Fn archive_read_support_format_zip
|
||||
enables support for both the streaming and the seeking zip readers,
|
||||
which can separately be enabled by respectively
|
||||
.Fn archive_read_support_format_zip_streamable
|
||||
and
|
||||
.Fn archive_read_support_format_zip_seekable
|
||||
.
|
||||
.It Fn archive_read_support_format_all
|
||||
Enables support for all available formats except the
|
||||
.Dq raw
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
struct read_fd_data {
|
||||
int fd;
|
||||
size_t block_size;
|
||||
int64_t size;
|
||||
char use_lseek;
|
||||
void *buffer;
|
||||
};
|
||||
@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
mine->use_lseek = 1;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(mine->fd, O_BINARY);
|
||||
@@ -131,7 +133,7 @@ static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
int64_t skip = request;
|
||||
off_t skip = (off_t)request;
|
||||
int64_t old_offset, new_offset;
|
||||
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
|
||||
|
||||
@@ -140,20 +142,25 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
/* Reduce a request that would overflow the 'skip' variable. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
skip = (off_t)max_skip;
|
||||
}
|
||||
|
||||
/* Reduce request to the next smallest multiple of block_size */
|
||||
request = (request / mine->block_size) * mine->block_size;
|
||||
if (request == 0)
|
||||
/* Reduce 'skip' to the next smallest multiple of block_size */
|
||||
skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
|
||||
if (skip == 0)
|
||||
return (0);
|
||||
|
||||
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
|
||||
((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
|
||||
return (new_offset - old_offset);
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
|
||||
if (old_offset >= mine->size ||
|
||||
skip > mine->size - old_offset) {
|
||||
/* Do not seek past end of file. */
|
||||
errno = ESPIPE;
|
||||
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
|
||||
/* If seek failed once, it will probably fail again. */
|
||||
mine->use_lseek = 0;
|
||||
@@ -178,11 +185,24 @@ static int64_t
|
||||
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_fd_data *mine = (struct read_fd_data *)client_data;
|
||||
off_t seek = (off_t)request;
|
||||
int64_t r;
|
||||
int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
/* See above for notes about when off_t is less than 64 bits. */
|
||||
r = lseek(mine->fd, request, whence);
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = (off_t)max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = (off_t)min_seek;
|
||||
}
|
||||
|
||||
r = lseek(mine->fd, seek, whence);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -52,13 +52,15 @@
|
||||
struct read_FILE_data {
|
||||
FILE *f;
|
||||
size_t block_size;
|
||||
int64_t size;
|
||||
void *buffer;
|
||||
char can_skip;
|
||||
};
|
||||
|
||||
static int file_close(struct archive *, void *);
|
||||
static ssize_t file_read(struct archive *, void *, const void **buff);
|
||||
static int64_t file_skip(struct archive *, void *, int64_t request);
|
||||
static int FILE_close(struct archive *, void *);
|
||||
static ssize_t FILE_read(struct archive *, void *, const void **buff);
|
||||
static int64_t FILE_seek(struct archive *, void *, int64_t, int);
|
||||
static int64_t FILE_skip(struct archive *, void *, int64_t);
|
||||
|
||||
int
|
||||
archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
@@ -69,7 +71,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
void *b;
|
||||
|
||||
archive_clear_error(a);
|
||||
mine = malloc(sizeof(*mine));
|
||||
mine = calloc(1, sizeof(*mine));
|
||||
b = malloc(block_size);
|
||||
if (mine == NULL || b == NULL) {
|
||||
archive_set_error(a, ENOMEM, "No memory");
|
||||
@@ -90,22 +92,23 @@ archive_read_open_FILE(struct archive *a, FILE *f)
|
||||
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
|
||||
/* Enable the seek optimization only for regular files. */
|
||||
mine->can_skip = 1;
|
||||
} else
|
||||
mine->can_skip = 0;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
|
||||
#if defined(__CYGWIN__) || defined(_WIN32)
|
||||
setmode(fileno(mine->f), O_BINARY);
|
||||
#endif
|
||||
|
||||
archive_read_set_read_callback(a, file_read);
|
||||
archive_read_set_skip_callback(a, file_skip);
|
||||
archive_read_set_close_callback(a, file_close);
|
||||
archive_read_set_read_callback(a, FILE_read);
|
||||
archive_read_set_skip_callback(a, FILE_skip);
|
||||
archive_read_set_seek_callback(a, FILE_seek);
|
||||
archive_read_set_close_callback(a, FILE_close);
|
||||
archive_read_set_callback_data(a, mine);
|
||||
return (archive_read_open1(a));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
file_read(struct archive *a, void *client_data, const void **buff)
|
||||
FILE_read(struct archive *a, void *client_data, const void **buff)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
size_t bytes_read;
|
||||
@@ -119,16 +122,17 @@ file_read(struct archive *a, void *client_data, const void **buff)
|
||||
}
|
||||
|
||||
static int64_t
|
||||
file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
FILE_skip(struct archive *a, void *client_data, int64_t request)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
#if HAVE_FSEEKO
|
||||
off_t skip = (off_t)request;
|
||||
#elif HAVE__FSEEKI64
|
||||
#if HAVE__FSEEKI64
|
||||
int64_t skip = request;
|
||||
#elif HAVE_FSEEKO
|
||||
off_t skip = (off_t)request;
|
||||
#else
|
||||
long skip = (long)request;
|
||||
#endif
|
||||
int64_t old_offset, new_offset = -1;
|
||||
int skip_bits = sizeof(skip) * 8 - 1;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
@@ -144,7 +148,7 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
/* If request is too big for a long or an off_t, reduce it. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
int64_t max_skip =
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
@@ -152,23 +156,92 @@ file_skip(struct archive *a, void *client_data, int64_t request)
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* fileno() isn't safe on all platforms ... see above. */
|
||||
if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
|
||||
old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = _ftelli64(mine->f);
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = ftello(mine->f);
|
||||
#else
|
||||
if (fseek(mine->f, skip, SEEK_CUR) != 0)
|
||||
old_offset = ftell(mine->f);
|
||||
#endif
|
||||
{
|
||||
mine->can_skip = 0;
|
||||
return (0);
|
||||
if (old_offset >= 0) {
|
||||
if (old_offset < mine->size &&
|
||||
skip <= mine->size - old_offset) {
|
||||
#ifdef __ANDROID__
|
||||
new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = _ftelli64(mine->f);
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = ftello(mine->f);
|
||||
#else
|
||||
if (fseek(mine->f, skip, SEEK_CUR) == 0)
|
||||
new_offset = ftell(mine->f);
|
||||
#endif
|
||||
if (new_offset >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
}
|
||||
return (request);
|
||||
|
||||
mine->can_skip = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Store the offset and use it in the read callback.
|
||||
*/
|
||||
static int64_t
|
||||
FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
#if HAVE__FSEEKI64
|
||||
int64_t seek = request;
|
||||
#elif HAVE_FSEEKO
|
||||
off_t seek = (off_t)request;
|
||||
#else
|
||||
long seek = (long)request;
|
||||
#endif
|
||||
int seek_bits = sizeof(seek) * 8 - 1;
|
||||
(void)a; /* UNUSED */
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = min_seek;
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* Newer Android versions have fseeko...to meditate. */
|
||||
int64_t ret = lseek(fileno(mine->f), seek, whence);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
#elif HAVE__FSEEKI64
|
||||
if (_fseeki64(mine->f, seek, whence) == 0) {
|
||||
return _ftelli64(mine->f);
|
||||
}
|
||||
#elif HAVE_FSEEKO
|
||||
if (fseeko(mine->f, seek, whence) == 0) {
|
||||
return ftello(mine->f);
|
||||
}
|
||||
#else
|
||||
if (fseek(mine->f, seek, whence) == 0) {
|
||||
return ftell(mine->f);
|
||||
}
|
||||
#endif
|
||||
/* If we arrive here, the input is corrupted or truncated so fail. */
|
||||
archive_set_error(a, errno, "Error seeking in FILE* pointer");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static int
|
||||
file_close(struct archive *a, void *client_data)
|
||||
FILE_close(struct archive *a, void *client_data)
|
||||
{
|
||||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ struct read_file_data {
|
||||
size_t block_size;
|
||||
void *buffer;
|
||||
mode_t st_mode; /* Mode bits for opened file. */
|
||||
int64_t size;
|
||||
char use_lseek;
|
||||
enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
|
||||
union {
|
||||
@@ -303,7 +304,7 @@ file_open(struct archive *a, void *client_data)
|
||||
}
|
||||
if (fd < 0) {
|
||||
archive_set_error(a, errno,
|
||||
"Failed to open '%S'", wfilename);
|
||||
"Failed to open '%ls'", wfilename);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#else
|
||||
@@ -315,7 +316,7 @@ file_open(struct archive *a, void *client_data)
|
||||
if (fstat(fd, &st) != 0) {
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if (mine->filename_type == FNT_WCS)
|
||||
archive_set_error(a, errno, "Can't stat '%S'",
|
||||
archive_set_error(a, errno, "Can't stat '%ls'",
|
||||
wfilename);
|
||||
else
|
||||
#endif
|
||||
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
|
||||
mine->st_mode = st.st_mode;
|
||||
|
||||
/* Disk-like inputs can use lseek(). */
|
||||
if (is_disk_like)
|
||||
if (is_disk_like) {
|
||||
mine->use_lseek = 1;
|
||||
mine->size = st.st_size;
|
||||
}
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
fail:
|
||||
@@ -447,7 +450,7 @@ file_read(struct archive *a, void *client_data, const void **buff)
|
||||
"Error reading '%s'", mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno,
|
||||
"Error reading '%S'", mine->filename.w);
|
||||
"Error reading '%ls'", mine->filename.w);
|
||||
}
|
||||
return (bytes_read);
|
||||
}
|
||||
@@ -479,21 +482,30 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
/* We use _lseeki64() on Windows. */
|
||||
int64_t old_offset, new_offset;
|
||||
int64_t old_offset, new_offset, skip = request;
|
||||
#else
|
||||
off_t old_offset, new_offset;
|
||||
off_t old_offset, new_offset, skip = (off_t)request;
|
||||
#endif
|
||||
int skip_bits = sizeof(skip) * 8 - 1;
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
|
||||
/* TODO: Deal with case where off_t isn't 64 bits.
|
||||
* This shouldn't be a problem on Linux or other POSIX
|
||||
* systems, since the configuration logic for libarchive
|
||||
* tries to obtain a 64-bit off_t.
|
||||
*/
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
|
||||
(new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
/* Reduce a request that would overflow the 'skip' variable. */
|
||||
if (sizeof(request) > sizeof(skip)) {
|
||||
const int64_t max_skip =
|
||||
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
|
||||
if (request > max_skip)
|
||||
skip = max_skip;
|
||||
}
|
||||
|
||||
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
|
||||
if (old_offset >= mine->size ||
|
||||
skip > mine->size - old_offset) {
|
||||
/* Do not seek past end of file. */
|
||||
errno = ESPIPE;
|
||||
} else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
|
||||
return (new_offset - old_offset);
|
||||
}
|
||||
|
||||
/* If lseek() fails, don't bother trying again. */
|
||||
mine->use_lseek = 0;
|
||||
@@ -509,7 +521,7 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
archive_set_error(a, errno, "Error seeking in '%ls'",
|
||||
mine->filename.w);
|
||||
return (-1);
|
||||
}
|
||||
@@ -540,11 +552,24 @@ static int64_t
|
||||
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
{
|
||||
struct read_file_data *mine = (struct read_file_data *)client_data;
|
||||
off_t seek = (off_t)request;
|
||||
int64_t r;
|
||||
int seek_bits = sizeof(seek) * 8 - 1;
|
||||
|
||||
/* We use off_t here because lseek() is declared that way. */
|
||||
/* See above for notes about when off_t is less than 64 bits. */
|
||||
r = lseek(mine->fd, request, whence);
|
||||
|
||||
/* Reduce a request that would overflow the 'seek' variable. */
|
||||
if (sizeof(request) > sizeof(seek)) {
|
||||
const int64_t max_seek =
|
||||
(((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1;
|
||||
const int64_t min_seek = ~max_seek;
|
||||
if (request > max_seek)
|
||||
seek = (off_t)max_seek;
|
||||
else if (request < min_seek)
|
||||
seek = (off_t)min_seek;
|
||||
}
|
||||
|
||||
r = lseek(mine->fd, seek, whence);
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
@@ -555,7 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence)
|
||||
archive_set_error(a, errno, "Error seeking in '%s'",
|
||||
mine->filename.m);
|
||||
else
|
||||
archive_set_error(a, errno, "Error seeking in '%S'",
|
||||
archive_set_error(a, errno, "Error seeking in '%ls'",
|
||||
mine->filename.w);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
@@ -37,46 +37,32 @@ archive_read_support_filter_by_code(struct archive *a, int filter_code)
|
||||
switch (filter_code) {
|
||||
case ARCHIVE_FILTER_NONE:
|
||||
return archive_read_support_filter_none(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GZIP:
|
||||
return archive_read_support_filter_gzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_BZIP2:
|
||||
return archive_read_support_filter_bzip2(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_COMPRESS:
|
||||
return archive_read_support_filter_compress(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZMA:
|
||||
return archive_read_support_filter_lzma(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_XZ:
|
||||
return archive_read_support_filter_xz(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_UU:
|
||||
return archive_read_support_filter_uu(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_RPM:
|
||||
return archive_read_support_filter_rpm(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZIP:
|
||||
return archive_read_support_filter_lzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LRZIP:
|
||||
return archive_read_support_filter_lrzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZOP:
|
||||
return archive_read_support_filter_lzop(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_GRZIP:
|
||||
return archive_read_support_filter_grzip(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZ4:
|
||||
return archive_read_support_filter_lz4(a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_ZSTD:
|
||||
return archive_read_support_filter_zstd(a);
|
||||
break;
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
@@ -328,6 +328,7 @@ next_code(struct archive_read_filter *self)
|
||||
static int debug_buff[1024];
|
||||
static unsigned debug_index;
|
||||
|
||||
again:
|
||||
code = newcode = getbits(self, state->bits);
|
||||
if (code < 0)
|
||||
return (code);
|
||||
@@ -360,7 +361,7 @@ next_code(struct archive_read_filter *self)
|
||||
state->section_end_code = (1 << state->bits) - 1;
|
||||
state->free_ent = 257;
|
||||
state->oldcode = -1;
|
||||
return (next_code(self));
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (code > state->free_ent
|
||||
|
||||
@@ -323,7 +323,6 @@ lz4_filter_read(struct archive_read_filter *self, const void **p)
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC, "Program error.");
|
||||
return (ARCHIVE_FATAL);
|
||||
break;
|
||||
}
|
||||
|
||||
while (state->stage == SELECT_STREAM) {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
@@ -50,6 +53,7 @@
|
||||
#include "archive_ppmd7_private.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_time_private.h"
|
||||
#include "archive_endian.h"
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
@@ -59,7 +63,26 @@
|
||||
#define _7ZIP_SIGNATURE "7z\xBC\xAF\x27\x1C"
|
||||
#define SFX_MIN_ADDR 0x27000
|
||||
#define SFX_MAX_ADDR 0x60000
|
||||
#define SFX_MAX_OFFSET (SFX_MAX_ADDR - SFX_MIN_ADDR)
|
||||
|
||||
/*
|
||||
* PE format
|
||||
*/
|
||||
#define PE_DOS_HDR_LEN 0x40
|
||||
#define PE_DOS_HDR_ELFANEW_OFFSET 0x3c
|
||||
#define PE_COFF_HDR_LEN 0x18
|
||||
#define PE_COFF_HDR_SEC_CNT_OFFSET 0x6
|
||||
#define PE_COFF_HDR_OPT_SZ_OFFSET 0x14
|
||||
#define PE_SEC_HDR_LEN 0x28
|
||||
#define PE_SEC_HDR_RAW_ADDR_OFFSET 0x14
|
||||
#define PE_SEC_HDR_RAW_SZ_OFFSET 0x10
|
||||
|
||||
/*
|
||||
* ELF format
|
||||
*/
|
||||
#define ELF_HDR_MIN_LEN 0x34
|
||||
#define ELF_HDR_EI_CLASS_OFFSET 0x04
|
||||
#define ELF_HDR_EI_DATA_OFFSET 0x05
|
||||
|
||||
/*
|
||||
* Codec ID
|
||||
@@ -83,6 +106,7 @@
|
||||
#define _7Z_ARM 0x03030501
|
||||
#define _7Z_ARMTHUMB 0x03030701
|
||||
#define _7Z_ARM64 0xa
|
||||
#define _7Z_RISCV 0xb
|
||||
#define _7Z_SPARC 0x03030805
|
||||
|
||||
#define _7Z_ZSTD 0x4F71101 /* Copied from https://github.com/mcmilk/7-Zip-zstd.git */
|
||||
@@ -144,7 +168,6 @@ struct _7z_digests {
|
||||
uint32_t *digests;
|
||||
};
|
||||
|
||||
|
||||
struct _7z_folder {
|
||||
uint64_t numCoders;
|
||||
struct _7z_coder {
|
||||
@@ -224,13 +247,13 @@ struct _7zip_entry {
|
||||
#define CRC32_IS_SET (1<<3)
|
||||
#define HAS_STREAM (1<<4)
|
||||
|
||||
time_t mtime;
|
||||
time_t atime;
|
||||
time_t ctime;
|
||||
long mtime_ns;
|
||||
long atime_ns;
|
||||
long ctime_ns;
|
||||
uint32_t mode;
|
||||
int64_t mtime;
|
||||
int64_t atime;
|
||||
int64_t ctime;
|
||||
uint32_t mtime_ns;
|
||||
uint32_t atime_ns;
|
||||
uint32_t ctime_ns;
|
||||
__LA_MODE_T mode;
|
||||
uint32_t attr;
|
||||
};
|
||||
|
||||
@@ -388,7 +411,6 @@ static int decode_encoded_header_info(struct archive_read *,
|
||||
static int decompress(struct archive_read *, struct _7zip *,
|
||||
void *, size_t *, const void *, size_t *);
|
||||
static ssize_t extract_pack_stream(struct archive_read *, size_t);
|
||||
static void fileTimeToUtc(uint64_t, time_t *, long *);
|
||||
static uint64_t folder_uncompressed_size(struct _7z_folder *);
|
||||
static void free_CodersInfo(struct _7z_coders_info *);
|
||||
static void free_Digest(struct _7z_digests *);
|
||||
@@ -424,7 +446,9 @@ static ssize_t read_stream(struct archive_read *, const void **, size_t,
|
||||
size_t);
|
||||
static int seek_pack(struct archive_read *);
|
||||
static int64_t skip_stream(struct archive_read *, size_t);
|
||||
static int skip_sfx(struct archive_read *, ssize_t);
|
||||
static int skip_sfx(struct archive_read *, const ssize_t);
|
||||
static ssize_t find_pe_overlay(struct archive_read *);
|
||||
static ssize_t find_elf_data_sec(struct archive_read *);
|
||||
static int slurp_central_directory(struct archive_read *, struct _7zip *,
|
||||
struct _7z_header_info *);
|
||||
static int setup_decode_folder(struct archive_read *, struct _7z_folder *,
|
||||
@@ -435,6 +459,8 @@ static void arm_Init(struct _7zip *);
|
||||
static size_t arm_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t arm64_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static ssize_t Bcj2_Decode(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t sparc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
static size_t powerpc_Convert(struct _7zip *, uint8_t *, size_t);
|
||||
|
||||
|
||||
int
|
||||
@@ -522,15 +548,17 @@ archive_read_format_7zip_bid(struct archive_read *a, int best_bid)
|
||||
* It may a 7-Zip SFX archive file. If first two bytes are
|
||||
* 'M' and 'Z' available on Windows or first four bytes are
|
||||
* "\x7F\x45LF" available on posix like system, seek the 7-Zip
|
||||
* signature. Although we will perform a seek when reading
|
||||
* a header, what we do not use __archive_read_seek() here is
|
||||
* due to a bidding performance.
|
||||
* signature. While find_pe_overlay can be performed without
|
||||
* performing a seek, find_elf_data_sec requires one,
|
||||
* thus a performance difference between the two is expected.
|
||||
*/
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
ssize_t offset = SFX_MIN_ADDR;
|
||||
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
|
||||
find_elf_data_sec(a);
|
||||
ssize_t offset = min_addr;
|
||||
ssize_t window = 4096;
|
||||
ssize_t bytes_avail;
|
||||
while (offset + window <= (SFX_MAX_ADDR)) {
|
||||
while (offset + window <= (min_addr + SFX_MAX_OFFSET)) {
|
||||
const char *buff = __archive_read_ahead(a,
|
||||
offset + window, &bytes_avail);
|
||||
if (buff == NULL) {
|
||||
@@ -580,21 +608,14 @@ check_7zip_header_in_sfx(const char *p)
|
||||
}
|
||||
|
||||
static int
|
||||
skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
skip_sfx(struct archive_read *a, const ssize_t min_addr)
|
||||
{
|
||||
const void *h;
|
||||
const char *p, *q;
|
||||
size_t skip, offset;
|
||||
ssize_t bytes, window;
|
||||
|
||||
/*
|
||||
* If bytes_avail > SFX_MIN_ADDR we do not have to call
|
||||
* __archive_read_seek() at this time since we have
|
||||
* already had enough data.
|
||||
*/
|
||||
if (bytes_avail > SFX_MIN_ADDR)
|
||||
__archive_read_consume(a, SFX_MIN_ADDR);
|
||||
else if (__archive_read_seek(a, SFX_MIN_ADDR, SEEK_SET) < 0)
|
||||
if (__archive_read_seek(a, min_addr, SEEK_SET) < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
offset = 0;
|
||||
@@ -627,7 +648,7 @@ skip_sfx(struct archive_read *a, ssize_t bytes_avail)
|
||||
(struct _7zip *)a->format->data;
|
||||
skip = p - (const char *)h;
|
||||
__archive_read_consume(a, skip);
|
||||
zip->seek_base = SFX_MIN_ADDR + offset + skip;
|
||||
zip->seek_base = min_addr + offset + skip;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
p += step;
|
||||
@@ -644,6 +665,207 @@ fatal:
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
find_pe_overlay(struct archive_read *a)
|
||||
{
|
||||
const char *h;
|
||||
ssize_t bytes, max_offset, offset, sec_end;
|
||||
ssize_t opt_hdr_sz, sec_cnt;
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Read Dos header to find e_lfanew
|
||||
*/
|
||||
h = __archive_read_ahead(a, PE_DOS_HDR_LEN, &bytes);
|
||||
if (h == NULL || h[0] != 'M' || h[1] != 'Z') {
|
||||
break;
|
||||
}
|
||||
offset = archive_le32dec(h + PE_DOS_HDR_ELFANEW_OFFSET);
|
||||
|
||||
/*
|
||||
* Read COFF header to find opt header size and sec cnt
|
||||
*/
|
||||
if (bytes < offset + PE_COFF_HDR_LEN) {
|
||||
h = __archive_read_ahead(a, offset + PE_COFF_HDR_LEN,
|
||||
&bytes);
|
||||
if (h == NULL || h[offset] != 'P' ||
|
||||
h[offset + 1] != 'E') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sec_cnt = archive_le16dec(
|
||||
h + offset + PE_COFF_HDR_SEC_CNT_OFFSET);
|
||||
opt_hdr_sz = archive_le16dec(
|
||||
h + offset + PE_COFF_HDR_OPT_SZ_OFFSET);
|
||||
|
||||
/*
|
||||
* Skip optional header
|
||||
*/
|
||||
if (opt_hdr_sz != 0) {
|
||||
offset += PE_COFF_HDR_LEN + opt_hdr_sz;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Traverse sec table to find max raw offset (i.e., overlay)
|
||||
*/
|
||||
if (bytes < offset + sec_cnt * PE_SEC_HDR_LEN) {
|
||||
h = __archive_read_ahead(a,
|
||||
offset + sec_cnt * PE_SEC_HDR_LEN, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
max_offset = offset;
|
||||
while (sec_cnt > 0) {
|
||||
sec_end = archive_le32dec(
|
||||
h + offset + PE_SEC_HDR_RAW_SZ_OFFSET) +
|
||||
archive_le32dec(
|
||||
h + offset + PE_SEC_HDR_RAW_ADDR_OFFSET);
|
||||
if (sec_end > max_offset) {
|
||||
max_offset = sec_end;
|
||||
}
|
||||
offset += PE_SEC_HDR_LEN;
|
||||
sec_cnt--;
|
||||
}
|
||||
return (max_offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* If encounter any weirdness, revert to old brute-force style search
|
||||
*/
|
||||
return (SFX_MIN_ADDR);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
find_elf_data_sec(struct archive_read *a)
|
||||
{
|
||||
const char *h;
|
||||
char big_endian, format_64;
|
||||
ssize_t bytes, min_addr = SFX_MIN_ADDR;
|
||||
uint64_t e_shoff, strtab_offset, strtab_size;
|
||||
uint16_t e_shentsize, e_shnum, e_shstrndx;
|
||||
uint16_t (*dec16)(const void *);
|
||||
uint32_t (*dec32)(const void *);
|
||||
uint64_t (*dec64)(const void *);
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* Read Elf header to find bitness & endianness
|
||||
*/
|
||||
h = __archive_read_ahead(a, ELF_HDR_MIN_LEN, &bytes);
|
||||
if (h == NULL || memcmp(h, "\x7F\x45LF", 4) != 0) {
|
||||
break;
|
||||
}
|
||||
format_64 = h[ELF_HDR_EI_CLASS_OFFSET] == 0x2;
|
||||
big_endian = h[ELF_HDR_EI_DATA_OFFSET] == 0x2;
|
||||
if (big_endian) {
|
||||
dec16 = &archive_be16dec;
|
||||
dec32 = &archive_be32dec;
|
||||
dec64 = &archive_be64dec;
|
||||
} else {
|
||||
dec16 = &archive_le16dec;
|
||||
dec32 = &archive_le32dec;
|
||||
dec64 = &archive_le64dec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read section header table info
|
||||
*/
|
||||
if (format_64) {
|
||||
e_shoff = (*dec64)(h + 0x28);
|
||||
e_shentsize = (*dec16)(h + 0x3A);
|
||||
e_shnum = (*dec16)(h + 0x3C);
|
||||
e_shstrndx = (*dec16)(h + 0x3E);
|
||||
if (e_shnum < e_shstrndx || e_shentsize < 0x28)
|
||||
break;
|
||||
|
||||
} else {
|
||||
e_shoff = (*dec32)(h + 0x20);
|
||||
e_shentsize = (*dec16)(h + 0x2E);
|
||||
e_shnum = (*dec16)(h + 0x30);
|
||||
e_shstrndx = (*dec16)(h + 0x32);
|
||||
if (e_shnum < e_shstrndx || e_shentsize < 0x18)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reading the section table to find strtab section
|
||||
*/
|
||||
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
if (format_64) {
|
||||
strtab_offset = (*dec64)(
|
||||
h + e_shstrndx * e_shentsize + 0x18);
|
||||
strtab_size = (*dec64)(
|
||||
h + e_shstrndx * e_shentsize + 0x20);
|
||||
} else {
|
||||
strtab_offset = (*dec32)(
|
||||
h + e_shstrndx * e_shentsize + 0x10);
|
||||
strtab_size = (*dec32)(
|
||||
h + e_shstrndx * e_shentsize + 0x14);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the STRTAB section to find the .data offset
|
||||
*/
|
||||
if (__archive_read_seek(a, strtab_offset, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, strtab_size, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
ssize_t data_sym_offset = -1;
|
||||
for (size_t offset = 0; offset < strtab_size - 6; offset++) {
|
||||
if (memcmp(h + offset, ".data\00", 6) == 0) {
|
||||
data_sym_offset = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (data_sym_offset == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the section with the .data name
|
||||
*/
|
||||
if (__archive_read_seek(a, e_shoff, SEEK_SET) < 0) {
|
||||
break;
|
||||
}
|
||||
h = __archive_read_ahead(a, (size_t)e_shnum * (size_t)e_shentsize, NULL);
|
||||
if (h == NULL) {
|
||||
break;
|
||||
}
|
||||
ssize_t sec_tbl_offset = 0, name_offset;
|
||||
while (e_shnum > 0) {
|
||||
name_offset = (*dec32)(h + sec_tbl_offset);
|
||||
if (name_offset == data_sym_offset) {
|
||||
if (format_64) {
|
||||
min_addr = (*dec64)(
|
||||
h + sec_tbl_offset + 0x18);
|
||||
} else {
|
||||
min_addr = (*dec32)(
|
||||
h + sec_tbl_offset + 0x10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
sec_tbl_offset += e_shentsize;
|
||||
e_shnum--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
__archive_read_seek(a, 0, SEEK_SET);
|
||||
return (min_addr);
|
||||
}
|
||||
|
||||
static int
|
||||
archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
struct archive_entry *entry)
|
||||
@@ -770,7 +992,7 @@ archive_read_format_7zip_read_header(struct archive_read *a,
|
||||
/* allocate for ",rdonly,hidden,system" */
|
||||
fflags_text = malloc(22 * sizeof(*fflags_text));
|
||||
if (fflags_text != NULL) {
|
||||
ptr = fflags_text;
|
||||
ptr = fflags_text;
|
||||
if (zip_entry->attr & FILE_ATTRIBUTE_READONLY) {
|
||||
strcpy(ptr, ",rdonly");
|
||||
ptr = ptr + 7;
|
||||
@@ -1109,7 +1331,9 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
if (coder2->codec != _7Z_X86 &&
|
||||
coder2->codec != _7Z_X86_BCJ2 &&
|
||||
coder2->codec != _7Z_ARM &&
|
||||
coder2->codec != _7Z_ARM64) {
|
||||
coder2->codec != _7Z_ARM64 &&
|
||||
coder2->codec != _7Z_POWERPC &&
|
||||
coder2->codec != _7Z_SPARC) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Unsupported filter %lx for %lx",
|
||||
@@ -1223,6 +1447,12 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
filters[fi].id = LZMA_FILTER_ARM64;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
#ifdef LZMA_FILTER_RISCV
|
||||
case _7Z_RISCV:
|
||||
filters[fi].id = LZMA_FILTER_RISCV;
|
||||
fi++;
|
||||
break;
|
||||
#endif
|
||||
case _7Z_SPARC:
|
||||
filters[fi].id = LZMA_FILTER_SPARC;
|
||||
@@ -1396,6 +1626,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
case _7Z_ARM:
|
||||
case _7Z_ARMTHUMB:
|
||||
case _7Z_ARM64:
|
||||
case _7Z_RISCV:
|
||||
case _7Z_SPARC:
|
||||
case _7Z_DELTA:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
@@ -1708,6 +1939,10 @@ decompress(struct archive_read *a, struct _7zip *zip,
|
||||
*outbytes = arm_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_ARM64) {
|
||||
*outbytes = arm64_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_SPARC) {
|
||||
*outbytes = sparc_Convert(zip, buff, *outbytes);
|
||||
} else if (zip->codec2 == _7Z_POWERPC) {
|
||||
*outbytes = powerpc_Convert(zip, buff, *outbytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2841,23 +3076,6 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
|
||||
static void
|
||||
fileTimeToUtc(uint64_t fileTime, time_t *timep, long *ns)
|
||||
{
|
||||
|
||||
if (fileTime >= EPOC_TIME) {
|
||||
fileTime -= EPOC_TIME;
|
||||
/* milli seconds base */
|
||||
*timep = (time_t)(fileTime / 10000000);
|
||||
/* nano seconds base */
|
||||
*ns = (long)(fileTime % 10000000) * 100;
|
||||
} else {
|
||||
*timep = 0;
|
||||
*ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
|
||||
{
|
||||
@@ -2900,19 +3118,19 @@ read_Times(struct archive_read *a, struct _7z_header_info *h, int type)
|
||||
goto failed;
|
||||
switch (type) {
|
||||
case kCTime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].ctime),
|
||||
&(entries[i].ctime_ns));
|
||||
entries[i].flg |= CTIME_IS_SET;
|
||||
break;
|
||||
case kATime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].atime),
|
||||
&(entries[i].atime_ns));
|
||||
entries[i].flg |= ATIME_IS_SET;
|
||||
break;
|
||||
case kMTime:
|
||||
fileTimeToUtc(archive_le64dec(p),
|
||||
ntfs_to_unix(archive_le64dec(p),
|
||||
&(entries[i].mtime),
|
||||
&(entries[i].mtime_ns));
|
||||
entries[i].flg |= MTIME_IS_SET;
|
||||
@@ -3007,7 +3225,9 @@ slurp_central_directory(struct archive_read *a, struct _7zip *zip,
|
||||
|
||||
if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
|
||||
/* This is an executable ? Must be self-extracting... */
|
||||
r = skip_sfx(a, bytes_avail);
|
||||
const ssize_t min_addr = p[0] == 'M' ? find_pe_overlay(a) :
|
||||
find_elf_data_sec(a);
|
||||
r = skip_sfx(a, min_addr);
|
||||
if (r < ARCHIVE_WARN)
|
||||
return (r);
|
||||
if ((p = __archive_read_ahead(a, 32, &bytes_avail)) == NULL)
|
||||
@@ -4007,6 +4227,121 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
sparc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
|
||||
// in https://git.tukaani.org/xz-embedded.git
|
||||
|
||||
/*
|
||||
* Branch/Call/Jump (BCJ) filter decoders
|
||||
*
|
||||
* Authors: Lasse Collin <lasse.collin@tukaani.org>
|
||||
* Igor Pavlov <https://7-zip.org/>
|
||||
*
|
||||
* Copyright (C) The XZ Embedded authors and contributors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this
|
||||
* software for any purpose with or without fee is hereby granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size_t i;
|
||||
uint32_t instr;
|
||||
|
||||
size &= ~(size_t)3;
|
||||
|
||||
for (i = 0; i < size; i += 4) {
|
||||
instr = (uint32_t)(buf[i] << 24)
|
||||
| ((uint32_t)buf[i+1] << 16)
|
||||
| ((uint32_t)buf[i+2] << 8)
|
||||
| (uint32_t)buf[i+3];
|
||||
|
||||
if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
|
||||
instr <<= 2;
|
||||
instr -= zip->bcj_ip + (uint32_t)i;
|
||||
instr >>= 2;
|
||||
instr = ((uint32_t)0x40000000 - (instr & 0x400000))
|
||||
| 0x40000000 | (instr & 0x3FFFFF);
|
||||
|
||||
buf[i] = (uint8_t)(instr >> 24);
|
||||
buf[i+1] = (uint8_t)(instr >> 16);
|
||||
buf[i+2] = (uint8_t)(instr >> 8);
|
||||
buf[i+3] = (uint8_t)instr;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static size_t
|
||||
powerpc_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
{
|
||||
// This function was adapted from
|
||||
// static size_t powerpc_code(void *simple, uint32_t now_pos, bool is_encoder, uint8_t *buffer, size_t size)
|
||||
// in https://git.tukaani.org/xz.git
|
||||
|
||||
/*
|
||||
* Filter for PowerPC (big endian) binaries
|
||||
*
|
||||
* Authors: Igor Pavlov
|
||||
* Lasse Collin
|
||||
*
|
||||
* Copyright (C) The XZ Utils authors and contributors
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this
|
||||
* software for any purpose with or without fee is hereby granted.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
size &= ~(size_t)3;
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < size; i += 4) {
|
||||
// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
|
||||
if ((buf[i] >> 2) == 0x12
|
||||
&& ((buf[i + 3] & 3) == 1)) {
|
||||
|
||||
const uint32_t src
|
||||
= (((uint32_t)(buf[i + 0]) & 3) << 24)
|
||||
| ((uint32_t)(buf[i + 1]) << 16)
|
||||
| ((uint32_t)(buf[i + 2]) << 8)
|
||||
| ((uint32_t)(buf[i + 3]) & ~UINT32_C(3));
|
||||
|
||||
uint32_t dest = src - (zip->bcj_ip + (uint32_t)(i));
|
||||
|
||||
buf[i + 0] = 0x48 | ((dest >> 24) & 0x03);
|
||||
buf[i + 1] = (dest >> 16);
|
||||
buf[i + 2] = (dest >> 8);
|
||||
buf[i + 3] &= 0x03;
|
||||
buf[i + 3] |= dest;
|
||||
}
|
||||
}
|
||||
|
||||
zip->bcj_ip += (uint32_t)i;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Brought from LZMA SDK.
|
||||
*
|
||||
@@ -4029,8 +4364,17 @@ arm64_Convert(struct _7zip *zip, uint8_t *buf, size_t size)
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||
#define RC_INIT2 zip->bcj2_code = 0; zip->bcj2_range = 0xFFFFFFFF; \
|
||||
{ int ii; for (ii = 0; ii < 5; ii++) { RC_TEST; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }}
|
||||
#define RC_INIT2 do { \
|
||||
zip->bcj2_code = 0; \
|
||||
zip->bcj2_range = 0xFFFFFFFF; \
|
||||
{ \
|
||||
int ii; \
|
||||
for (ii = 0; ii < 5; ii++) { \
|
||||
RC_TEST; \
|
||||
zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define NORMALIZE if (zip->bcj2_range < kTopValue) { RC_TEST; zip->bcj2_range <<= 8; zip->bcj2_code = (zip->bcj2_code << 8) | RC_READ_BYTE; }
|
||||
|
||||
@@ -4177,4 +4521,3 @@ Bcj2_Decode(struct _7zip *zip, uint8_t *outBuf, size_t outSize)
|
||||
|
||||
return ((ssize_t)outPos);
|
||||
}
|
||||
|
||||
@@ -41,49 +41,34 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
|
||||
switch (format_code & ARCHIVE_FORMAT_BASE_MASK) {
|
||||
case ARCHIVE_FORMAT_7ZIP:
|
||||
return archive_read_support_format_7zip(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_AR:
|
||||
return archive_read_support_format_ar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CAB:
|
||||
return archive_read_support_format_cab(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_CPIO:
|
||||
return archive_read_support_format_cpio(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_EMPTY:
|
||||
return archive_read_support_format_empty(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ISO9660:
|
||||
return archive_read_support_format_iso9660(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_LHA:
|
||||
return archive_read_support_format_lha(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_MTREE:
|
||||
return archive_read_support_format_mtree(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR:
|
||||
return archive_read_support_format_rar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR_V5:
|
||||
return archive_read_support_format_rar5(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAW:
|
||||
return archive_read_support_format_raw(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
return archive_read_support_format_tar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_WARC:
|
||||
return archive_read_support_format_warc(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_XAR:
|
||||
return archive_read_support_format_xar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_ZIP:
|
||||
return archive_read_support_format_zip(a);
|
||||
break;
|
||||
}
|
||||
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
|
||||
"Invalid format code specified");
|
||||
|
||||
@@ -363,7 +363,12 @@ archive_read_support_format_cab(struct archive *_a)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_string_init(&cab->ws);
|
||||
archive_wstring_ensure(&cab->ws, 256);
|
||||
if (archive_wstring_ensure(&cab->ws, 256) == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory");
|
||||
free(cab);
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
r = __archive_read_register_format(a,
|
||||
cab,
|
||||
|
||||
@@ -189,6 +189,7 @@ struct cpio {
|
||||
};
|
||||
|
||||
static int64_t atol16(const char *, unsigned);
|
||||
static uint64_t atol16u(const char *, unsigned);
|
||||
static int64_t atol8(const char *, unsigned);
|
||||
static int archive_read_format_cpio_bid(struct archive_read *, int);
|
||||
static int archive_read_format_cpio_options(struct archive_read *,
|
||||
@@ -835,6 +836,7 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
|
||||
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
|
||||
{
|
||||
int64_t t;
|
||||
uint64_t u;
|
||||
const void *h;
|
||||
const char *header;
|
||||
|
||||
@@ -851,12 +853,12 @@ header_afiol(struct archive_read *a, struct cpio *cpio,
|
||||
|
||||
archive_entry_set_dev(entry,
|
||||
(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
|
||||
t = atol16(header + afiol_ino_offset, afiol_ino_size);
|
||||
if (t < 0) {
|
||||
archive_set_error(&a->archive, 0, "Nonsensical ino value");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_entry_set_ino(entry, t);
|
||||
u = atol16u(header + afiol_ino_offset, afiol_ino_size);
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
archive_entry_set_ino(entry, (int64_t)(u & INT64_MAX));
|
||||
#else
|
||||
archive_entry_set_ino(entry, u);
|
||||
#endif
|
||||
archive_entry_set_mode(entry,
|
||||
(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
|
||||
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
|
||||
@@ -1030,6 +1032,12 @@ atol8(const char *p, unsigned char_cnt)
|
||||
|
||||
static int64_t
|
||||
atol16(const char *p, unsigned char_cnt)
|
||||
{
|
||||
return ((int64_t)atol16u(p, char_cnt));
|
||||
}
|
||||
|
||||
static uint64_t
|
||||
atol16u(const char *p, unsigned char_cnt)
|
||||
{
|
||||
uint64_t l;
|
||||
int digit;
|
||||
@@ -1048,7 +1056,7 @@ atol16(const char *p, unsigned char_cnt)
|
||||
l <<= 4;
|
||||
l |= digit;
|
||||
}
|
||||
return ((int64_t)l);
|
||||
return (l);
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
Loaded 100 of 568 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user