Age | Commit message (Collapse) | Author | Files | Lines |
|
Now the two variations of the format strings are created with
a macro, and the whole detection code can be easily disabled
on platforms where thousand separator formatting is known to
not work (MSVC has no support, and on DJGPP 2.05 it can have
problems in some cases).
|
|
SSIZE_MAX isn't readily available on MSVC. Removing it means
that there is one thing less to worry when porting to MSVC.
|
|
This check was extended to test the code added to fix a failing assert
in ae5c07b22a6b3766b84f409f1b6b5c100469068a.
|
|
|
|
|
|
The argument to vli_ceil4() should always guarantee the return value
is also a valid lzma_vli. Thus the highest three valid lzma_vli values
are invalid arguments. All uses of the function ensure this so the
assert is updated to match this.
|
|
This was not a security bug since there was no path to overflow
UINT64_MAX in lzma_index_append() or when it calls index_file_size().
The bug was discovered by a failing assert() in vli_ceil4() when called
from index_file_size() when unpadded_sum (the sum of the compressed size
of current Stream and the unpadded_size parameter) exceeds LZMA_VLI_MAX.
Previously, the unpadded_size parameter was checked to be not greater
than UNPADDED_SIZE_MAX, but no check was done once compressed_base was
added.
This could not have caused an integer overflow in index_file_size() when
called by lzma_index_append(). The calculation for file_size breaks down
into the sum of:
- Compressed base from all previous Streams
- 2 * LZMA_STREAM_HEADER_SIZE (size of the current Streams header and
footer)
- stream_padding (can be set by lzma_index_stream_padding())
- Compressed base from the current Stream
- Unpadded size (parameter to lzma_index_append())
The sum of everything except for Unpadded size must be less than
LZMA_VLI_MAX. This is guarenteed by overflow checks in the functions
that can set these values including lzma_index_stream_padding(),
lzma_index_append(), and lzma_index_cat(). The maximum value for
Unpadded size is enforced by lzma_index_append() to be less than or
equal UNPADDED_SIZE_MAX. Thus, the sum cannot exceed UINT64_MAX since
LZMA_VLI_MAX is half of UINT64_MAX.
Thanks to Joona Kannisto for reporting this.
|
|
|
|
|
|
The Autotools build allows win95 threads and --enable-small together now
if the compiler supports __attribute__((__constructor__)).
|
|
|
|
When the compiler supports __attribute__((__constructor__))
mythread_once() is never used, even with --enable-small. A configuration
with win95 threads and --enable-small will compile and be thread safe so
it can be allowed.
This isn't a very common configuration since MSVC does not support
__attribute__((__constructor__)), but MINGW32 and CLANG32 environments
for MSYS2 can use win95 threads and have
__attribute__((__constructor__)) support.
|
|
The "once_" variable was accidentally referred to as just "once". This
prevented building with Vista threads when
HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR was not defined.
|
|
The .codespellrc allows setting default options to avoid false positive
matches, set additional dictionaries, etc. For now, codespell can be
used locally before committing doc and comment changes.
It should help prevent silly errors and fix up commits in the future.
|
|
|
|
|
|
|
|
|
|
groff defaults to SGR escapes. Using -P-c passes -c to grotty
which restores the old behavior. Perhaps there is a better way to
get pure plain text output but this works for now.
|
|
|
|
|
|
signal.h in WASI SDK doesn't currently provide sigprocmask()
or sigset_t. liblzma doesn't need them so this change makes
liblzma and xzdec build against WASI SDK. xz doesn't build yet
and the tests don't either as tuktest needs setjmp() which
isn't (yet?) implemented in WASI SDK.
Closes: https://github.com/tukaani-project/xz/pull/57
See also: https://github.com/tukaani-project/xz/pull/56
(The original commit was edited a little by Lasse Collin.)
|
|
Newline was accidentally removed in commit
01cbb7f023ee7fda8ddde04bd17cf7d3c2418706.
|
|
|
|
|
|
The CMake build will try to create broken symlinks on Unix and Unix-like
platforms. Cygwin and MSYS2 are Unix-like, but may not be able to create
broken symlinks. The value of the CYGWIN or MSYS environment variables
determine if broken symlinks are valid.
The default for MSYS2 does not allow for broken symlinks, so the CMake
build has been broken for MSYS2 since commit
80a1a8bb838842a2be343bd88ad1462c21c5e2c9.
|
|
All of the MSYS2 environments need make, and it does not come with the
toolchain package. The toolchain package will install the needed
compiler toolchains since without this package CMake cannot properly
generate the Makefiles.
|
|
The default for many of the MSYS2 environments is for CMake to create
Ninja build files. This would complicate the build script since we would
need a different command to run the tests. Its simpler to always use
Unix Makefiles so that "make test" is always a usable target for
testing.
|
|
|
|
Calling the MSYS2 environment "system" was a bit vague and should be
more specific.
|
|
|
|
To workaround Automake lacking Windows resource compiler support, an
empty source file is compiled to overwrite the resource files for static
library builds. Translation units without an external declaration are
not allowed by the C standard and result in a warning when used with
-Wempty-translation-unit (Clang) or -pedantic (GCC).
|
|
|
|
Only a subset of the tests run by the Linux and MacOS Autotools builds
are run. The most interesting tests are the ones that disable threads,
encoders, and decoders.
The Windows runner will only be run manually since these tests will
likely take much longer than the Linux and MacOS runners. This runner
should be used before merging any large features and before releases.
Currently the clang64 environment fails to due to a warning and
-Werror is enabled for the CI tests. This is still an early version
since the CMake build can be done for MSVC and optionally each of the
MSYS2 environments. GitHub does not allow manually running the CI tests
unless the workflow is checked on the default branch so checking in a
minimum version is a good idea.
Thanks to Arthur S for the original proposing the original patch.
Closes: https://github.com/tukaani-project/xz/pull/34
|
|
|
|
Previously if the lzip decoder was not configured then test_files.sh
would pass the lzip tests instead of skipping them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Clang 16.0.0 and earlier have a bug that the ifunc resolver function
triggers the -Wunused-function warning. The resolver function is static
and only "used" by the __attribute__((__ifunc()__)).
At this time, the bug is still unresolved, but has been reported:
https://github.com/llvm/llvm-project/issues/63957
This is not a problem in GCC.
|
|
This further improves the documentation from commit
f36ca7982f6bd5e9827219ed4f3c5a1fbf5d7bdf. The previous wording of
"supported options" was slightly misleading since the options that are
printed are the ones that are relevant for encoding/decoding. It is not
about which options can or must be specified.
|
|
The comment used "flag" when referring to decoder options. Just
referring to them as options is more clear and consistent.
|
|
This string is used to print a filename when using "xz -v" and
stderr isn't a terminal.
|
|
|
|
Maybe ICC always #defines _MSC_VER on Windows but now
it's very clear which code will get used.
|
|
|
|
|
|
The new Tests section describes basic information about the tests, how
to run them, and important details when cross compiling. We have had a
few questions about how to compile the tests without running them, so
hopefully this information will help others with the same question in the
future.
Fixes: https://github.com/tukaani-project/xz/issues/54
|
|
This adds an entry to "Other implementations of the .xz format" for
XZ for Java.
|
|
The Memory limit information section described three output
columns when it actually has six. This was reworded to
"multiple" to make it more future proof.
|
|
* Moved max_block_list_size from a global to local variable.
* Reworded error message in validate_block_list_filter().
* Removed helper function filter_chain_error().
* Changed 1 << X to 1U << X in many places
|
|
|
|
|
|
Changed will print => prints in xz --robot --version description to
match --robot --info-memory description.
|
|
The order is now consistent with the order the command line arguments
are documented earlier in the man page. The new order is:
1. --list
2. --info-memory
3. --version
Instead of the previous order:
1. --version
2. --info-memory
3. --list
|
|
|
|
The --filters-help can be used to help create filter chains with the
--filters and --filtersX options. The message in --long-help is too
short to fully explain the syntax to construct complex filter chains.
In --robot mode, xz will only print the output from liblzma function
lzma_str_list_filters.
|
|
The --block-list option description needed updating since the new
--filtersX option changes how it can be used. The new entry for
--filters1=FILTERS ... --filter9=FILTERS was created right after
the --filters option.
|
|
|
|
If a filter chain is set but not used in --block-list, it introduced
unexpected behavior such as requiring an unneeded amount of memory to
compress, reducing the number of threads in multi-threaded encoding, and
printing an incorrect amount of memory needed to decompress.
This also renames filters_init_mask => filters_used_mask. A filter is
assumed to be used if it is specified in --filtersX until
coder_set_compression_settings() determines which filters are referenced
in --block-list.
|
|
When opt_block_size is not used, the Block size for mt encoder is
derived from the minimum of the largest Block specified by
--block-list and the recommended Block size on all filter chains
calculated by lzma_mt_block_size(). This avoids using unnecessary
memory and ensures that all Blocks are large enough for the most memory
needy filter chain.
|
|
|
|
Previously, only the default filter chain could have its memory usage
adjusted. The filter chains specified with --filtersX were not checked
for memory usage. Now, all used filter chains will be adjusted if
necessary.
|
|
The block splitting logic and split_block() function are not needed if
encoders are disabled. This will help slightly reduce the binary size
when built without encoders and allow split_block() to use functions
that require encoders being enabled.
|
|
This will only free filter chains created with --filters1-9 since the
default filter chain may be set from a static function variable. The
complexity to free the default filter chain is not worth the burden on
code maintenance.
|
|
--block-list is only supported with compression in xz format. This avoids
silently ignoring when --block-list is unused.
|
|
The new command line options are meant to be combined with --block-list.
They work as an optional extension to --block-list to specify a custom
filter chain for each block listed. The new options allow the creation
of up to 9 reusable filter chains. For instance:
xz --block-list=1:10MiB,3:5MiB,,2:5MiB,1:0 --filters1=delta--lzma2 \
--filters2=x86--lzma2 --filters3=arm64--lzma2
Will create the following blocks:
1. A block of size 10 MiB with filter chain delta, lzma2.
2. A block of size 5 MiB with filter chain arm64, lzma2.
3. A block of size 5 MiB with filter chain arm64, lzma2.
4. A block of size 5 MiB with filter chain x86, lzma2.
5. A block containing the rest of the file contents with filter chain
delta, lzma2.
|
|
This is a little cleaner than the previous implementation of
forget_filter_chain(). It is also more consistent since
lzma_str_to_filters() will always terminate the filter chain so there
is no need to terminate it later in coder_set_compression_settings().
|
|
Converting from string to filter will also need to be done for block
specific filter chains.
|
|
|
|
|
|
The --filters option uses the new lzma_str_to_filters() function
to convert a string into a full filter chain. Using this option
will reset all previous filters set by --preset, --[filter], or
--filters.
|
|
Fixed a bug where test_compress_* would all fail if arm64 or armthumb
filters were enabled for compression but arm was disabled. Since the
grep tests only checked for "define HAVE_ENCODER_ARM", this would match
on HAVE_ENCODER_ARM64 or HAVE_ENCODER_ARMTHUMB.
Now the config.h feature test requires " 1" at the end to prevent the
prefix problem. have_feature() was also updated for this even though
there were known current bugs affecting it. This is just in case future
features have a similar prefix problem.
|
|
|
|
Commit 78704f36e74205857c898a351c757719a6c8b666 added an empty
initializer {} to prevent a warning. The empty initializer is a GNU
extension and results in a build failure on MSVC. The -wpedantic flag
warns about empty initializers.
|
|
|
|
Several tests were missing calls to lzma_index_end() to clean up the
lzma_index structs. The memory leaks were discovered by using
-fsanitize=address with GCC.
|
|
test_block_header was not properly freeing the filter options between
calls to lzma_block_header_decode(). The memory leaks were discovered by
using -fsanitize=address with GCC.
|
|
This change only impacts the compiler warning since it was impossible
for the wait_abs struct in stream_encode_mt() to be used before it was
initialized since mythread_condtime_set() will always be called before
mythread_cond_timedwait().
Since the mythread.h code is different between the POSIX and
Windows versions, this warning was only present on Windows builds.
Thanks to Arthur S for reporting the warning and providing an initial
patch.
|
|
In lzma_memcmplen(), the <intrin.h> header file is only included if
_MSC_VER and _M_X64 are both defined but _BitScanForward64() was
previously used if _M_X64 was defined. GCC for MSYS2 defines _M_X64 but
not _MSC_VER so _BitScanForward64() was used without including
<intrin.h>.
Now, lzma_memcmplen() will use __builtin_ctzll() for MSYS2 GCC builds as
expected.
|
|
ci_build.sh was updated to accept disabling of __attribute__ ifunc
and CLMUL. This will allow -fsanitize=address to pass because ifunc
is incompatible with -fsanitize=address. The CLMUL implementation has
optimizations that potentially read past the buffer and mask out the
unwanted bytes.
This test will only run on Autotools Linux.
|
|
|
|
|
|
|
|
|
|
It's so that there's a clear difference in wording compared
to liblzma's integrity check types.
|
|
The ifunc method avoids indirection via the function pointer
crc64_func. This works on GNU/Linux and probably on FreeBSD too.
The previous __attribute((__constructor__)) method is kept for
compatibility with ELF platforms which do support ifunc.
The ifunc method has some limitations, for example, building
liblzma with -fsanitize=address will result in segfaults.
The configure option --disable-ifunc must be used for such builds.
Thanks to Hans Jansen for the original patch.
Closes: https://github.com/tukaani-project/xz/pull/53
|
|
CMake build system will now verify if __attribute__((__ifunc__())) can be
used in the build system. If so, HAVE_FUNC_ATTRIBUTE_IFUNC will be
defined to 1.
|
|
configure.ac will now verify if __attribute__((__ifunc__())) can be used in
the build system. If so, HAVE_FUNC_ATTRIBUTE_IFUNC will be defined to 1.
|
|
Without the extra command, all of the CI tests were automatically
failing because the Ubuntu servers could not be reached properly.
|
|
|
|
Boost iostream uses `find_package` in quiet mode and then again uses
`find_package` with required. This second call triggers a
`add_library cannot create imported target "ZLIB::ZLIB" because another
target with the same name already exists.`
This can simply be fixed by skipping the alias part on secondary
`find_package` runs.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Reword "options required" to "supported options". The previous may have
suggested that the options listed were all required anytime a filter is
used for encoding or decoding. The reword makes this more clear that
adjusting the options is optional.
|
|
None of the liblzma functions may throw an exception, so this
attribute should be applied to all liblzma API functions.
|
|
The lzma_mt_block_size() was previously just an internal function for
the multithreaded .xz encoder. It is used to provide a recommended Block
size for a given filter chain.
This function is helpful to determine the maximum Block size for the
multithreaded .xz encoder when one wants to change the filters between
blocks. Then, this determined Block size can be provided to
lzma_stream_encoder_mt() in the lzma_mt options parameter when
intializing the coder. This requires one to know all the filter chains
they are using before starting to encode (or at least the filter chain
that will need the largest Block size), but that isn't a bad limitation.
|
|
This creates an internal liblzma macro to test if the dictionary size
is valid for encoding.
|
|
|
|
|
|
|
|
Previous commit 6be460dde07113fe3f08f814b61ddc3264125a96 would cause an
error if the integer size was 32 bit.
|
|
|
|
Wrong line was changed in 7062348bf35c1e4cbfee00ad9fffb4a21aa6eff7.
Also, this has >= instead of == since ints larger than 32 bits would
work too even if not relevant in practice.
|
|
|
|
|
|
|
|
Legacy Windows did not need to #include <intrin.h> to use the MSVC
intrinsics. Newer versions likely just issue a warning, but the MSVC
documentation says to include the header file for the intrinsics we use.
GCC and Clang can "pretend" to be MSVC on Windows, so extra checks are
needed in tuklib_integer.h to only include <intrin.h> when it will is
actually needed.
|
|
Clang has support for __builtin_clz(), but previously Clang would
fallback to either the MSVC intrinsic or the regular C code. This was
discovered due to a bug where a new version of Clang required the
<intrin.h> header file in order to use the MSVC intrinsics.
Thanks to Anton Kochkov for notifying us about the bug.
|
|
AUTHORS was updated earlier, lzma.h was simply forgotten.
|
|
|
|
|
|
|
|
|
|
Signed-off-by: Gabriela Gutierrez <gabigutierrez@google.com>
|
|
|
|
If the cache file is not removed, CMake will not reset configurations
back to their default values. In order to make the tests independent, it
is simplest to purge the cache. Unfortunatly, this will slow down the
tests a little and repeat some checks.
|
|
Now that the threading is configurable, the liblzma CMake package only
needs the threading library when using POSIX threads.
|
|
The thread method is now configurable for the CMake build. It matches
the Autotools build by allowing ON (pick the best threading method),
OFF (no threading), posix, win95, and vista. If both Windows and
posix threading are both available, then ON will choose Windows
threading. Windows threading will also not use:
target_link_libraries(liblzma Threads::Threads)
since on systems like MinGW-w64 it would link the posix threads
without purpose.
|
|
Now, CMake will run similar feature disable tests that the Autotools
version did before. In order to do this without repeating lines in
ci.yml, it now makes sense to use the GitHub Workflow matrix to create
a loop.
|
|
Also included various clean ups for style and helper functions for
repeated work.
|
|
This script is only meant to be run as part of the CI build/test process
on machines that are known to have bash (Ubuntu and MacOS). If this
assumption changes in the future, then the bash specific commands will
need to be replaced with a more portable option. For now, it is
convenient to use bash commands.
|
|
|
|
|
|
It adds only one new policy related to FOLDERS which we don't use.
This makes it clear that the code is compatible with the policies
up to 3.26.
|
|
|
|
This allows users to change the features they build either in
CMakeCache.txt or by using a CMake GUI. The sources built for
liblzma are affected by this too, so only the necessary files
will be compiled.
|
|
It's obsolete in Autoconf >= 2.70 and just an alias for AC_PROG_CC
but Autoconf 2.69 requires AC_PROG_CC_C99 to get a C99 compiler.
|
|
This makes no functional difference in the generated configure
(at least with the Autotools versions I have installed) but this
change might prevent future bugs like the one that was just
fixed in the commit 5a5bd7f871818029d5ccbe189f087f591258c294.
|
|
|
|
This is broken in the releases 5.2.6 to 5.4.2. A workaround
for these releases is to pass EGREP='grep -E' as an argument
to configure in addition to --disable-threads.
The problem appeared when m4/ax_pthread.m4 was updated in
the commit 6629ed929cc7d45a11e385f357ab58ec15e7e4ad which
introduced the use of AC_EGREP_CPP. AC_EGREP_CPP calls
AC_REQUIRE([AC_PROG_EGREP]) to set the shell variable EGREP
but this was only executed if POSIX threads were enabled.
Libtool code also has AC_REQUIRE([AC_PROG_EGREP]) but Autoconf
omits it as AC_PROG_EGREP has already been required earlier.
Thus, if not using POSIX threads, the shell variable EGREP
would be undefined in the Libtool code in configure.
ax_pthread.m4 is fine. The bug was in configure.ac which called
AX_PTHREAD conditionally in an incorrect way. Using AS_CASE
ensures that all AC_REQUIREs get always run.
Thanks to Frank Busse for reporting the bug.
Fixes: https://github.com/tukaani-project/xz/issues/45
|
|
Thanks to Christian Hesse for reporting the issue.
Fixes: https://github.com/tukaani-project/xz/issues/44
|
|
|
|
|
|
|
|
The xz man page timestamp was intentionally left unchanged.
|
|
|
|
|
|
These should have been included in 5.3.2alpha already.
|
|
These should have been included in 5.3.2alpha already.
|
|
|
|
|
|
|
|
When the docs are installed, calling the directory "liblzma" is
confusing since multiple other files in the doc directory are for
liblzma. This should also make it more natural for distros when they
package the documentation.
|
|
This was left in by mistake since an early version of the ARM64 filter
used a different struct for its options.
|
|
Autogen now requires --no-doxygen or having doxygen installed to run
without errors.
|
|
|
|
|
|
The \mainpage command is used in the first block of comments in lzma.h.
This changes the previously nearly empty index.html to use the first
comment block in lzma.h for its contents.
lzma.h is no longer documented separately, but this is for the better
since lzma.h only defined a few macros that users do not need to use.
The individual API header files all have a disclaimer that they should
not be #included directly, so there should be no confusion on the fact
that lzma.h should be the only header used by applications.
Additionally, the note "See ../lzma.h for information about liblzma as
a whole." was removed since lzma.h is now the main page of the
generated HTML and does not have its own page anymore. So it would be
confusing in the HTML version and was only a "nice to have" when
browsing the source files.
|
|
Another command line option (--no-doxygen) was added to disable
creating the doxygen documenation in cases where it not wanted or
if the doxygen tool is not installed.
|
|
This is a helper script to generate the Doxygen documentation. It can be
run in 'liblzma' or 'internal' mode by setting the first argument. It
will default to 'liblzma' mode and only generate documentation for the
liblzma API header files.
The helper script will be run during the custom mydist hook when we
create releases. This hook already alters the source directory, so its
fine to do it here too. This way, we can include the Doxygen generated
files in the distrubtion and when installing.
In 'liblzma' mode, the JavaScript is stripped from the .html files and
the .js files are removed. This avoids license hassle from jQuery and
other libraries that Doxygen 1.9.6 puts into jquery.js in minified form.
|
|
Added a install-data-local target to install the Doxygen documentation
only when it has been generated. In order to correctly remove the docs,
a corresponding uninstall-local target was added.
If the doxygen docs exist in the source tree, they will also be included
in the distribution now too.
|
|
Instead of having Doxyfile.in configured by Autoconf, the Doxyfile
can have the tags that need to be configured piped into the doxygen
command through stdin with the overrides after Doxyfile's contents.
Going forward, the documentation should be generated in two different
modes: liblzma or internal.
liblzma is useful for most users. It is the documentation for just
the liblzma API header files. This is the default.
internal is for people who want to understand how xz and liblzma work.
It might be useful for people who want to contribute to the project.
|
|
|
|
|
|
Converts the existing lzma_index tests into tuktests and covers every
API function from index.h except for lzma_file_info_decoder, which can
be tested in the future.
|
|
Also remove unneeded "sandbox_allowed = false;" as this code
will never be run more than once (making it work with multiple
input files isn't trivial).
|
|
|
|
The warning causes the exit status to be 2, so this will cause problems
for many scripted use cases for xz. The sandbox usage is already very
limited already, so silently disabling this allows it to be more usable.
|
|
Thanks to Xin Li for recommending the fix.
|
|
The warning is only used when errno == ENOSYS. Otherwise, xz still
issues a fatal error.
|
|
If a system has the Capsicum header files but does not actually
implement the system calls, then this would render xz unusable. Instead,
we can check if errno == ENOSYS and not issue a fatal error.
|
|
cap_enter() puts the process into the sandbox. If later calls to
cap_rights_limit() fail, then the process can still have some extra
protections.
|
|
lzma_lzma_preset() does not guarentee that the lzma_options_lzma are
usable in an encoder even if it returns false (success). If liblzma
is built with default configurations, then the options will always be
usable. However if the match finders hc3, hc4, or bt4 are disabled, then
the options may not be usable depending on the preset level requested.
The documentation was updated to reflect this complexity, since this
behavior was unclear before.
|
|
Thanks to autoantwort for reporting the issue and suggesting
a different patch:
https://github.com/tukaani-project/xz/pull/42
|
|
The static global variables can be disabled if encoders and decoders
are not built. If they are not disabled and -Werror is used, it will
cause an usused warning as an error.
|
|
The '\n' renders as a newline when the comments are converted to html
by Doxygen.
|
|
Shorten the description for lzma_raw_encoder_memusage() and
lzma_raw_decoder_memusage().
|
|
|
|
All functions now explicitly specify parameter and return values.
The notes and code annotations were moved before the parameter and
return value descriptions for consistency.
Also, the description above lzma_filter_encoder_is_supported() about
not being able to list available filters was removed since
lzma_str_list_filters() will do this.
|
|
|
|
In the C99 and C17 standards, section 6.5.6 paragraph 8 means that
adding 0 to a null pointer is undefined behavior. As of writing,
"clang -fsanitize=undefined" (Clang 15) diagnoses this. However,
I'm not aware of any compiler that would take advantage of this
when optimizing (Clang 15 included). It's good to avoid this anyway
since compilers might some day infer that pointer arithmetic implies
that the pointer is not NULL. That is, the following foo() would then
unconditionally return 0, even for foo(NULL, 0):
void bar(char *a, char *b);
int foo(char *a, size_t n)
{
bar(a, a + n);
return a == NULL;
}
In contrast to C, C++ explicitly allows null pointer + 0. So if
the above is compiled as C++ then there is no undefined behavior
in the foo(NULL, 0) call.
To me it seems that changing the C standard would be the sane
thing to do (just add one sentence) as it would ensure that a huge
amount of old code won't break in the future. Based on web searches
it seems that a large number of codebases (where null pointer + 0
occurs) are being fixed instead to be future-proof in case compilers
will some day optimize based on it (like making the above foo(NULL, 0)
return 0) which in the worst case will cause security bugs.
Some projects don't plan to change it. For example, gnulib and thus
many GNU tools currently require that null pointer + 0 is defined:
https://lists.gnu.org/archive/html/bug-gnulib/2021-11/msg00000.html
https://www.gnu.org/software/gnulib/manual/html_node/Other-portability-assumptions.html
In XZ Utils null pointer + 0 issue should be fixed after this
commit. This adds a few if-statements and thus branches to avoid
null pointer + 0. These check for size > 0 instead of ptr != NULL
because this way bugs where size > 0 && ptr == NULL will likely
get caught quickly. None of them are in hot spots so it shouldn't
matter for performance.
A little less readable version would be replacing
ptr + offset
with
offset != 0 ? ptr + offset : ptr
or creating a macro for it:
#define my_ptr_add(ptr, offset) \
((offset) != 0 ? ((ptr) + (offset)) : (ptr))
Checking for offset != 0 instead of ptr != NULL allows GCC >= 8.1,
Clang >= 7, and Clang-based ICX to optimize it to the very same code
as ptr + offset. That is, it won't create a branch. So for hot code
this could be a good solution to avoid null pointer + 0. Unfortunately
other compilers like ICC 2021 or MSVC 19.33 (VS2022) will create a
branch from my_ptr_add().
Thanks to Marcin Kowalczyk for reporting the problem:
https://github.com/tukaani-project/xz/issues/36
|
|
|
|
|
|
|