Compare commits

...
Author SHA1 Message Date
Alex Butler 6d69c4aad4 aarch64: MTE compatible strncmp
Add support for MTE to strncmp. Regression tested with xcheck and benchmarked
with glibc's benchtests on the Cortex-A53, Cortex-A72, and Neoverse N1.

The existing implementation assumes that any access to the pages in which the
string resides is safe. This assumption is not true when MTE is enabled. This
patch updates the algorithm to ensure that accesses remain within the bounds
of an MTE tag (16-byte chunks) and improves overall performance.

Co-authored-by: Branislav Rankov <branislav.rankov@arm.com>
Co-authored-by: Wilco Dijkstra <wilco.dijkstra@arm.com>
(cherry picked from commit 03e1378f94)
2024-11-04 17:15:10 +00:00
Andreas Schwab 73886db621 wordexp: handle overflow in positional parameter number (bug 28011)
Use strtoul instead of atoi so that overflow can be detected.

(cherry picked from commit 5adda61f62)
2021-07-06 19:04:26 +00:00
DJ Delorie c49cbcdc32 nscd: Fix double free in netgroupcache [BZ #27462]
In commit 745664bd79 a use-after-free
was fixed, but this led to an occasional double-free.  This patch
tracks the "live" allocation better.

Tested manually by a third party.

Related: RHBZ 1927877

Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit dca565886b)
2021-03-08 10:12:28 +00:00
Florian Weimer 2777e19c05 nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
addinnetgrX may use the heap-allocated buffer, so free the buffer
in this function.

(cherry picked from commit 745664bd79)
2021-03-08 10:12:28 +00:00
Siddhesh Poyarekar 3668134a9e Add NEWS entry for CVE-2020-29562 (BZ #26923)
BZ #26923 now has a CVE entry, so add a NEWS entry for it.

(cherry picked from commit 38a9e93cb1)
2021-01-03 12:21:12 +00:00
Michael Colavita 5fa7884e25 iconv: Fix incorrect UCS4 inner loop bounds (BZ#26923)
Previously, in UCS4 conversion routines we limit the number of
characters we examine to the minimum of the number of characters in the
input and the number of characters in the output. This is not the
correct behavior when __GCONV_IGNORE_ERRORS is set, as we do not consume
an output character when we skip a code unit. Instead, track the input
and output pointers and terminate the loop when either reaches its
limit.

This resolves assertion failures when resetting the input buffer in a step of
iconv, which assumes that the input will be fully consumed given sufficient
output space.

(cherry picked from commit 228edd356f)
2021-01-03 12:21:12 +00:00
Arjun Shankar d8ae6c00a9 iconv: Accept redundant shift sequences in IBM1364 [BZ #26224]
The IBM1364, IBM1371, IBM1388, IBM1390 and IBM1399 character sets
share converter logic (iconvdata/ibm1364.c) which would reject
redundant shift sequences when processing input in these character
sets.  This led to a hang in the iconv program (CVE-2020-27618).

This commit adjusts the converter to ignore redundant shift sequences
and adds test cases for iconv_prog hangs that would be triggered upon
their rejection.  This brings the implementation in line with other
converters that also ignore redundant shift sequences (e.g. IBM930
etc., fixed in commit 692de4b396).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 9a99c68214)
2020-11-30 22:59:53 +00:00
Arjun Shankar 670c675da3 intl: Handle translation output codesets with suffixes [BZ #26383]
Commit 91927b7c76 (Rewrite iconv option parsing [BZ #19519]) did not
handle cases where the output codeset for translations (via the `gettext'
family of functions) might have a caller specified encoding suffix such as
TRANSLIT or IGNORE.  This led to a regression where translations did not
work when the codeset had a suffix.

This commit fixes the above issue by parsing any suffixes passed to
__dcigettext and adds two new test-cases to intl/tst-codeset.c to
verify correct behaviour.  The iconv-internal function __gconv_create_spec
and the static iconv-internal function gconv_destroy_spec are now visible
internally within glibc and used in intl/dcigettext.c.

(cherry picked from commit 7d4ec75e11)
2020-11-30 22:59:53 +00:00
Aurelien Jarno 8fb94f8824 Add NEWS entry for CVE-2016-10228 (bug 19519)
(cherry picked from commit 17a0126abf)
2020-11-30 22:59:53 +00:00
Arjun Shankar ec51be40c7 Rewrite iconv option parsing [BZ #19519]
This commit replaces string manipulation during `iconv_open' and iconv_prog
option parsing with a structured, flag based conversion specification.  In
doing so, it alters the internal `__gconv_open' interface and accordingly
adjusts its uses.

This change fixes several hangs in the iconv program and therefore includes
a new test to exercise iconv_prog options that originally led to these hangs.
It also includes a new regression test for option handling in the iconv
function.

Reviewed-by: Florian Weimer <fweimer@redhat.com>
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 91927b7c76)
2020-11-30 22:59:53 +00:00
Arjun Shankar bdaa594506 support: Add xsetlocale function
(cherry picked from commit cce35a50c1)
2020-11-30 22:59:53 +00:00
Arjun Shankar 68d583bb1c Add Transliterations for Unicode Misc. Mathematical Symbols-A/B [BZ #23132]
This commit adds previously missing transliterations for several code points
in the Unicode blocks "Miscellaneous Mathematical Symbols-A/B" -
transliterated to their approximate ASCII representations.  It also adds a
corresponding iconv transliteration test.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 513aaa0d78)
2020-11-30 22:59:53 +00:00
Florian Weimer 222b1517cd support: Correct error message for TEST_COMPARE_STRING
It should say "string", not "blob".

(cherry picked from commit 6175507c06)
2020-11-30 22:59:53 +00:00
Adhemerval Zanella 62df32d604 support: Fix printf format for TEST_COMPARE_STRING
Fix the following on 32 bits targets:

support_test_compare_string.c: In function 'support_test_compare_string':
support_test_compare_string.c:80:37: error: format '%lu' expects argument of
type 'long unsigned int', but argument 2 has type 'size_t' {aka 'unsigned int'}
[-Werror=format=]
         printf ("  string length: %lu bytes\n", left_length);
                                   ~~^           ~~~~~~~~~~~
                                   %u
Checked on arm-linux-gnueabihf.

	* support/support_test_compare_string.c
	(support_test_compare_string): Fix printf format.

(cherry picked from commit 00c86a37d1)
2020-11-30 22:59:53 +00:00
Florian Weimer 711f183508 support: Implement TEST_COMPARE_STRING
(cherry picked from commit 1df872fd74)
2020-11-30 22:59:53 +00:00
Andreas Schwab 8b84316420 Fix iconv buffer handling with IGNORE error handler (bug #18830)
(cherry picked from commit 4802be92c8)
2020-11-30 22:59:53 +00:00
Aurelien Jarno 477587c75e Add NEWS entry for CVE-2020-10029 (bug 25487)
(cherry picked from commit 15ab195229)
2020-11-30 22:59:53 +00:00
Florian Weimer 4b8628acab math/test-sinl-pseudo: Use stack protector only if available
This fixes commit 9333498794 ("Avoid ldbl-96 stack
corruption from range reduction of pseudo-zero (bug 25487).").

(cherry picked from commit c10acd4026)
2020-11-30 22:59:53 +00:00
Joseph Myers 59420258af Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487).
Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero
argument (an representation where all the significand bits, including
the explicit high bit, are zero, but the exponent is not zero, which
is not a valid representation for the long double type).

Although this is not a valid long double representation, existing
practice in this area (see bug 4586, originally marked invalid but
subsequently fixed) is that we still seek to avoid invalid memory
accesses as a result, in case of programs that treat arbitrary binary
data as long double representations, although the invalid
representations of the ldbl-96 format do not need to be consistently
handled the same as any particular valid representation.

This patch makes the range reduction detect pseudo-zero and unnormal
representations that would otherwise go to __kernel_rem_pio2, and
returns a NaN for them instead of continuing with the range reduction
process.  (Pseudo-zero and unnormal representations whose unbiased
exponent is less than -1 have already been safely returned from the
function before this point without going through the rest of range
reduction.)  Pseudo-zero representations would previously result in
the value passed to __kernel_rem_pio2 being all-zero, which is
definitely unsafe; unnormal representations would previously result in
a value passed whose high bit is zero, which might well be unsafe
since that is not a form of input expected by __kernel_rem_pio2.

Tested for x86_64.

(cherry picked from commit 9333498794)
2020-11-30 22:59:53 +00:00
Aurelien Jarno e075046743 Add NEWS entry for CVE-2020-1751 (bug 25423)
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 07d16a6deb)
2020-11-16 08:00:00 +00:00
Aurelien Jarno daf88b1dd1 Add NEWS entry for CVE-2020-6096 (bug 25620)
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 17400c4bcd)
2020-11-16 08:00:00 +00:00
Alexander Anisimov b29853702e arm: CVE-2020-6096: Fix multiarch memcpy for negative length [BZ #25620]
Unsigned branch instructions could be used for r2 to fix the wrong
behavior when a negative length is passed to memcpy.
This commit fixes the armv7 version.

(cherry picked from commit beea361050)
2020-11-16 08:00:00 +00:00
Evgeny Eremin bad8d5ff60 arm: CVE-2020-6096: fix memcpy and memmove for negative length [BZ #25620]
Unsigned branch instructions could be used for r2 to fix the wrong
behavior when a negative length is passed to memcpy and memmove.
This commit fixes the generic arm implementation of memcpy amd memmove.

(cherry picked from commit 79a4fa341b)
2020-11-16 08:00:00 +00:00
Andreas Schwab d64ad0a517 Fix use-after-free in glob when expanding ~user (bug 25414)
The value of `end_name' points into the value of `dirname', thus don't
deallocate the latter before the last use of the former.

(cherry picked from commit ddc650e9b3)
(cherry picked from commit 39a05214fe)
2020-11-16 08:00:00 +00:00
Andreas Schwab 34ce87638c Fix array overflow in backtrace on PowerPC (bug 25423)
When unwinding through a signal frame the backtrace function on PowerPC
didn't check array bounds when storing the frame address.  Fixes commit
d400dcac5e ("PowerPC: fix backtrace to handle signal trampolines").

(cherry picked from commit d937694059)
2020-11-16 08:00:00 +00:00
Florian Weimer 0df8ecff9e misc/test-errno-linux: Handle EINVAL from quotactl
In commit 3dd4d40b420846dd35869ccc8f8627feef2cff32 ("xfs: Sanity check
flags of Q_XQUOTARM call"), Linux 5.4 added checking for the flags
argument, causing the test to fail due to too restrictive test
expectations.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 1f7525d924)
2020-11-16 08:00:00 +00:00
Kamlesh Kumar 26f5442ec1 <string.h>: Define __CORRECT_ISO_CPP_STRING_H_PROTO for Clang [BZ #25232]
Without the asm redirects, strchr et al. are not const-correct.

libc++ has a wrapper header that works with and without
__CORRECT_ISO_CPP_STRING_H_PROTO (using a Clang extension).  But when
Clang is used with libstdc++ or just C headers, the overloaded functions
with the correct types are not declared.

This change does not impact current GCC (with libstdc++ or libc++).

(cherry picked from commit 953ceff17a)
2020-11-16 08:00:00 +00:00
Aurelien Jarno 4b64a4245c intl/tst-gettext: fix failure with newest msgfmt
Since upstream gettext commit d13f165b83 (msgfmt: Remove
POT-Creation-Date field from the header in the output.), msgfmt does not
copy the POT-Creation-Date field in the header entry from the po file to
the mo file anymore. This breaks the assumption that we can test gettext
by comparing each message in the po files with the corresponding string
return by gettext. This makes the intl/tst-gettext to fail.

While it would have been possible to modify the po2test.awk script to
also strip the line POT-Creation-Date field when creating the msgs.h
file, it would not work with both the old and new msgfmt.

Instead create a tst-gettext-de.po file from de.po by removing the
POT-Creation-Date line. Another alternative would be to use a static
tst-gettext-de.po file, but I guess the reason for using de.po is to
also catch issues caused by newly added strings.

As tst-catgets also uses msg.h, it should also be updated. Instead of
using the new tst-gettext-de.po file, the patch modifies xopen-msg.awk
to avoid creating a second catgets->intl dependency.

Changelog:
	[BZ #21508]
	* catgets/xopen-msg.awk: Ignore POT-Creation-Date line.
	* intl/Makefile ($(objpfx)tst-gettext-de.po): Generate
	intl/tst-gettext-de.po from po/de.po by removing the
	POT-Creation-Date line.
	($(objpfx)msgs.h): Depend on $(objpfx)tst-gettext-de.po instead of
	../po/de.po.
	* intl/tst-gettext.sh: Use ${objpfx}tst-gettext-de.po instead of
	../po/de.po.
(cherry picked from commit 56456a2aad)
2020-11-16 08:00:00 +00:00
Szabolcs Nagy dc7f51bda9 aarch64: Fix DT_AARCH64_VARIANT_PCS handling [BZ #26798]
The variant PCS support was ineffective because in the common case
linkmap->l_mach.plt == 0 but then the symbol table flags were ignored
and normal lazy binding was used instead of resolving the relocs early.
(This was a misunderstanding about how GOT[1] is setup by the linker.)

In practice this mainly affects SVE calls when the vector length is
more than 128 bits, then the top bits of the argument registers get
clobbered during lazy binding.

Fixes bug 26798.

(cherry picked from commit 558251bd87)
2020-11-04 12:30:21 +00:00
Szabolcs Nagy 8edc96aa33 aarch64: add HWCAP_ATOMICS to HWCAP_IMPORTANT
This enables searching shared libraries in atomics/ when the hardware
supports LSE atomics of armv8.1 so one can provide optimized variants
of libraries in a portable way.

LSE atomics does not affect library abi, the new instructions can
interoperate with old ones.

I considered the earlier comments on the patch

https://sourceware.org/ml/libc-alpha/2018-04/msg00400.html
https://sourceware.org/ml/libc-alpha/2018-04/msg00625.html

It turns out that the way glibc dynamic linker decides on the search
path is not very flexible: it wants to use hwcap bits and associated
strings.  So some targets reuse hwcap bits for glibc internal purposes
to affect the search logic.  But hwcap is an interface with the kernel,
glibc should not allocate bits in it for its internal logic as that
limits future hwcap extensions and confusing to users who expect to see
hwcap bits in ifunc resolvers.  Instead of rewriting the dynamic linker
path logic (which affects all targets) this patch just uses the existing
mechanism, however this means that the path name has to be the hwcap
name "atomics" and cannot be changed to something more meaningful to
users.

It is hard to tell how much performance benefit this can give, in
principle armv8.1 atomics can be better optimized in the hardware, so it
can make a difference for synchronization heavy code.  On some systems
such multilib setup may be the only viable way to get optimized
libraries used.

	* sysdeps/unix/sysv/linux/aarch64/dl-procinfo.h (HWCAP_IMPORTANT): Add
	HWCAP_ATOMICS.

(cherry picked from commit 397c54c1af)
2020-03-25 16:24:32 +00:00
Szabolcs Nagy 599ebfacc0 aarch64: Remove HWCAP_CPUID from HWCAP_IMPORTANT
This partially reverts

commit f82e9672ad
Author:     Siddhesh Poyarekar <siddhesh@sourceware.org>

    aarch64: Allow overriding HWCAP_CPUID feature check using HWCAP_MASK

The idea was to make it possible to disable cpuid based ifunc resolution
in glibc by changing the hwcap mask which the user could already control.

However the hwcap mask has an orthogonal role: it specifies additional
library search paths for the dynamic linker.  So "cpuid" got added to
the search paths when it was set in the default mask (HWCAP_IMPORTANT),
which is not useful behaviour, the hwcap masking should not be reused
in the cpu features code.

Meanwhile there is a tunable to set the cpu explicitly so it is possible
to disable the cpuid based dispatch without using a hwcap mask:

  GLIBC_TUNABLES=glibc.tune.cpu=generic

	* sysdeps/unix/sysv/linux/aarch64/cpu-features.c (init_cpu_features):
	Use dl_hwcap without masking.
	* sysdeps/unix/sysv/linux/aarch64/dl-procinfo.h (HWCAP_IMPORTANT):
	Remove HWCAP_CPUID.

(cherry picked from commit d0cd798071)
2020-03-25 16:24:01 +00:00
Florian Weimer bef0b1cb31 libio: Disable vtable validation for pre-2.1 interposed handles [BZ #25203]
Commit c402355dfa ("libio: Disable
vtable validation in case of interposition [BZ #23313]") only covered
the interposable glibc 2.1 handles, in libio/stdfiles.c.  The
parallel code in libio/oldstdfiles.c needs similar detection logic.

Fixes (again) commit db3476aff1
("libio: Implement vtable verification [BZ #20191]").

Change-Id: Ief6f9f17e91d1f7263421c56a7dc018f4f595c21
(cherry picked from commit cb61630ed7)
2019-11-28 14:42:32 +01:00
Marcin Kościelnicki 4d5cfeb510 rtld: Check __libc_enable_secure before honoring LD_PREFER_MAP_32BIT_EXEC (CVE-2019-19126) [BZ #25204]
The problem was introduced in glibc 2.23, in commit
b9eb92ab05
("Add Prefer_MAP_32BIT_EXEC to map executable pages with MAP_32BIT").

(cherry picked from commit d5dfad4326)
2019-11-22 13:40:07 +01:00
Dragan Mladjenovic 92f04eedb5 mips: Force RWX stack for hard-float builds that can run on pre-4.8 kernels
Linux/Mips kernels prior to 4.8 could potentially crash the user
process when doing FPU emulation while running on non-executable
user stack.

Currently, gcc doesn't emit .note.GNU-stack for mips, but that will
change in the future. To ensure that glibc can be used with such
future gcc, without silently resulting in binaries that might crash
in runtime, this patch forces RWX stack for all built objects if
configured to run against minimum kernel version less than 4.8.

	* sysdeps/unix/sysv/linux/mips/Makefile
	(test-xfail-check-execstack):
	Move under mips-has-gnustack != yes.
	(CFLAGS-.o*, ASFLAGS-.o*): New rules.
	Apply -Wa,-execstack if mips-force-execstack == yes.
	* sysdeps/unix/sysv/linux/mips/configure: Regenerated.
	* sysdeps/unix/sysv/linux/mips/configure.ac
	(mips-force-execstack): New var.
	Set to yes for hard-float builds with minimum_kernel < 4.8.0
	or minimum_kernel not set at all.
	(mips-has-gnustack): New var.
	Use value of libc_cv_as_noexecstack
	if mips-force-execstack != yes, otherwise set to no.

(cherry picked from commit 33bc9efd91)
2019-11-05 14:25:38 -03:00
Wilco Dijkstra 5b4f7382af Add undef to fix test failure. 2019-09-13 16:35:12 +01:00
Wilco Dijkstra 9456483fb2 Improve performance of memmem
This patch significantly improves performance of memmem using a novel
modified Horspool algorithm.  Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.

By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.

Small needles up to size 2 use a dedicated linear search.  Very long needles
use the Two-Way algorithm (to avoid increasing stack size or slowing down
the common case, inlining is disabled).

The performance gain is 6.6 times on English text on AArch64 using random
needles with average size 8.

Tested against GLIBC testsuite and randomized tests.

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>

	* string/memmem.c (__memmem): Rewrite to improve performance.

(cherry picked from commit 680942b016)
2019-09-13 15:50:08 +01:00
Wilco Dijkstra 373f8b06a3 Improve performance of strstr
This patch significantly improves performance of strstr using a novel
modified Horspool algorithm.  Needles up to size 256 use a bad-character
table indexed by hashed pairs of characters to quickly skip past mismatches.
Long needles use a self-adapting filtering step to avoid comparing the whole
needle repeatedly.

By limiting the needle length to 256, the shift table only requires 8 bits
per entry, lowering preprocessing overhead and minimizing cache effects.
This limit also implies worst-case performance is linear.

Small needles up to size 3 use a dedicated linear search.  Very long needles
use the Two-Way algorithm.

The performance gain using the improved bench-strstr on Cortex-A72 is 5.8
times basic_strstr and 3.7 times twoway_strstr.

Tested against GLIBC testsuite, randomized tests and the GNULIB strstr test
(https://git.savannah.gnu.org/cgit/gnulib.git/tree/tests/test-strstr.c).

Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>

	* string/str-two-way.h (two_way_short_needle): Add inline to avoid
	warning.
	(two_way_long_needle): Block inlining.
	* string/strstr.c (strstr2): Add new function.
	(strstr3): Likewise.
	(STRSTR): Completely rewrite strstr to improve performance.

(cherry picked from commit 5e0a7ecb66)
2019-09-13 15:50:02 +01:00
Wilco Dijkstra 4ec1b9e913 Fix strstr bug with huge needles (bug 23637)
The generic strstr in GLIBC 2.28 fails to match huge needles.  The optimized
AVAILABLE macro reads ahead a large fixed amount to reduce the overhead of
repeatedly checking for the end of the string.  However if the needle length
is larger than this, two_way_long_needle may confuse this as meaning the end
of the string and return NULL.  This is fixed by adding the needle length to
the amount to read ahead.

	[BZ #23637]
	* string/test-strstr.c (pr23637): New function.
	(test_main): Add tests with longer needles.
	* string/strcasestr.c (AVAILABLE): Fix readahead distance.
	* string/strstr.c (AVAILABLE): Likewise.

(cherry picked from commit 83a552b0bb)
2019-09-13 15:49:20 +01:00
Rajalakshmi Srinivasaraghavan ecd6271ed8 Speedup first memmem match
As done in commit 284f42bc77, memcmp
can be used after memchr to avoid the initialization overhead of the
two-way algorithm for the first match.  This has shown improvement
>40% for first match.

(cherry picked from commit c8dd67e7c9)
2019-09-13 15:48:19 +01:00
Wilco Dijkstra bba6b9288f Simplify and speedup strstr/strcasestr first match
Looking at the benchtests, both strstr and strcasestr spend a lot of time
in a slow initialization loop handling one character per iteration.
This can be simplified and use the much faster strlen/strnlen/strchr/memcmp.
Read ahead a few cachelines to reduce the number of strnlen calls, which
improves performance by ~3-4%.  This patch improves the time taken for the
full strstr benchtest by >40%.

	* string/strcasestr.c (STRCASESTR): Simplify and speedup first match.
	* string/strstr.c (AVAILABLE): Likewise.

(cherry picked from commit 284f42bc77)
2019-09-13 15:47:22 +01:00
Wilco Dijkstra 7a4da6ef7a Improve strstr performance
Improve strstr performance.  Strstr tends to be slow because it uses
many calls to memchr and a slow byte loop to scan for the next match.
Performance is significantly improved by using strnlen on larger blocks
and using strchr to search for the next matching character.  strcasestr
can also use strnlen to scan ahead, and memmem can use memchr to check
for the next match.

On the GLIBC bench tests the performance gains on Cortex-A72 are:
strstr: +25%
strcasestr: +4.3%
memmem: +18%

On a 256KB dataset strstr performance improves by 67%, strcasestr by 47%.

    Reviewd-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

(cherry picked from commit 3ae725dfb6)
2019-09-13 15:46:16 +01:00
Wilco Dijkstra 5f0d2e0491 [AArch64] Add ifunc support for Ares
Add Ares to the midr_el0 list and support ifunc dispatch.  Since Ares
supports 2 128-bit loads/stores, use Neon registers for memcpy by
selecting __memcpy_falkor by default (we should rename this to
__memcpy_simd or similar).

	* manual/tunables.texi (glibc.cpu.name): Add ares tunable.
	* sysdeps/aarch64/multiarch/memcpy.c (__libc_memcpy): Use
	__memcpy_falkor for ares.
	* sysdeps/unix/sysv/linux/aarch64/cpu-features.h (IS_ARES):
	Add new define.
	* sysdeps/unix/sysv/linux/aarch64/cpu-features.c (cpu_list):
	Add ares cpu.

(cherry picked from commit 02f440c1ef)
2019-09-06 18:53:37 +01:00
Siddhesh Poyarekar e6b7252040 aarch64,falkor: Use vector registers for memcpy
Vector registers perform better than scalar register pairs for copying
data so prefer them instead.  This results in a time reduction of over
50% (i.e. 2x speed improvemnet) for some smaller sizes for memcpy-walk.
Larger sizes show improvements of around 1% to 2%.  memcpy-random shows
a very small improvement, in the range of 1-2%.

	* sysdeps/aarch64/multiarch/memcpy_falkor.S (__memcpy_falkor):
	Use vector registers.

(cherry picked from commit 0aec4c1d18)
2019-09-06 18:38:56 +01:00
Siddhesh Poyarekar c74b884f70 aarch64,falkor: Ignore prefetcher tagging for smaller copies
For smaller and medium sized copies, the effect of hardware
prefetching are not as dominant as instruction level parallelism.
Hence it makes more sense to load data into multiple registers than to
try and route them to the same prefetch unit.  This is also the case
for the loop exit where we are unable to latch on to the same prefetch
unit anyway so it makes more sense to have data loaded in parallel.

The performance results are a bit mixed with memcpy-random, with
numbers jumping between -1% and +3%, i.e. the numbers don't seem
repeatable.  memcpy-walk sees a 70% improvement (i.e. > 2x) for 128
bytes and that improvement reduces down as the impact of the tail copy
decreases in comparison to the loop.

	* sysdeps/aarch64/multiarch/memcpy_falkor.S (__memcpy_falkor):
	Use multiple registers to copy data in loop tail.

(cherry picked from commit db725a458e)
2019-09-06 18:36:23 +01:00
Siddhesh Poyarekar 0fc5934ebd aarch64/strncmp: Use lsr instead of mov+lsr
A lsr can do what the mov and lsr did.

(cherry picked from commit b47c3e7637)
2019-09-06 17:00:32 +01:00
Siddhesh Poyarekar e0a0bd3acc aarch64/strncmp: Unbreak builds with old binutils
Binutils 2.26.* and older do not support moves with shifted registers,
so use a separate shift instruction instead.

(cherry picked from commit d46f84de74)
2019-09-06 16:59:34 +01:00
Siddhesh Poyarekar 638caf3000 aarch64: Improve strncmp for mutually misaligned inputs
The mutually misaligned inputs on aarch64 are compared with a simple
byte copy, which is not very efficient.  Enhance the comparison
similar to strcmp by loading a double-word at a time.  The peak
performance improvement (i.e. 4k maxlen comparisons) due to this on
the strncmp microbenchmark is as follows:

falkor: 3.5x (up to 72% time reduction)
cortex-a73: 3.5x (up to 71% time reduction)
cortex-a53: 3.5x (up to 71% time reduction)

All mutually misaligned inputs from 16 bytes maxlen onwards show
upwards of 15% improvement and there is no measurable effect on the
performance of aligned/mutually aligned inputs.

	* sysdeps/aarch64/strncmp.S (count): New macro.
	(strncmp): Store misaligned length in SRC1 in COUNT.
	(mutual_align): Adjust.
	(misaligned8): Load dword at a time when it is safe.

(cherry picked from commit 7108f1f944)
2019-09-06 16:58:29 +01:00
Siddhesh Poyarekar d5f45a29ff aarch64/strcmp: fix misaligned loop jump target
I accidentally set the loop jump back label as misaligned8 instead of
do_misaligned.  The typo is harmless but it's always nice to not have
to unnecessarily execute those two instructions.

	* sysdeps/aarch64/strcmp.S (do_misaligned): Jump back to
	do_misaligned, not misaligned8.

(cherry picked from commit 6ca24c4348)
2019-09-06 16:57:46 +01:00
Siddhesh Poyarekar 7f690fafad aarch64: Improve strcmp unaligned performance
Replace the simple byte-wise compare in the misaligned case with a
dword compare with page boundary checks in place.  For simplicity I've
chosen a 4K page boundary so that we don't have to query the actual
page size on the system.

This results in up to 3x improvement in performance in the unaligned
case on falkor and about 2.5x improvement on mustang as measured using
bench-strcmp.

	* sysdeps/aarch64/strcmp.S (misaligned8): Compare dword at a
	time whenever possible.

(cherry picked from commit 2bce01ebba)
2019-09-06 16:56:45 +01:00
Siddhesh Poyarekar 40df047b3b aarch64: Fix branch target to loop16
I goofed up when changing the loop8 name to loop16 and missed on out
the branch instance.  Fixed and actually build tested this time.

	* sysdeps/aarch64/memcmp.S (more16): Fix branch target loop16.

(cherry picked from commit 4e54d91863)
2019-09-06 16:20:12 +01:00
Siddhesh Poyarekar 062139f233 aarch64: Optimized memcmp for medium to large sizes
This improved memcmp provides a fast path for compares up to 16 bytes
and then compares 16 bytes at a time, thus optimizing loads from both
sources.  The glibc memcmp microbenchmark retains performance (with an
error of ~1ns) for smaller compare sizes and reduces up to 31% of
execution time for compares up to 4K on the APM Mustang.  On Qualcomm
Falkor this improves to almost 48%, i.e. it is almost 2x improvement
for sizes of 2K and above.

	* sysdeps/aarch64/memcmp.S: Widen comparison to 16 bytes at a
	time.

(cherry picked from commit 30a81dae5b)
2019-09-06 16:19:07 +01:00
Siddhesh Poyarekar f3e2add213 aarch64: Use the L() macro for labels in memcmp
The L() macro makes the assembly a bit more readable.

	* sysdeps/aarch64/memcmp.S: Use L() macro for labels.

(cherry picked from commit 84c94d2fd9)
2019-09-06 16:17:01 +01:00
Adhemerval Zanella 22bd3ab40e posix: Fix large mmap64 offset for mips64n32 (BZ#24699)
The fix for BZ#21270 (commit 158d5fa0e1) added a mask to avoid offset larger
than 1^44 to be used along __NR_mmap2.  However mips64n32 users __NR_mmap,
as mips64n64, but still defines off_t as old non-LFS type (other ILP32, such
x32, defines off_t being equal to off64_t).  This leads to use the same
mask meant only for __NR_mmap2 call for __NR_mmap, thus limiting the maximum
offset it can use with mmap64.

This patch fixes by setting the high mask only for __NR_mmap2 usage. The
posix/tst-mmap-offset.c already tests it and also fails for mips64n32. The
patch also change the test to check for an arch-specific header that defines
the maximum supported offset.

Checked on x86_64-linux-gnu, i686-linux-gnu, and I also tests tst-mmap-offset
on qemu simulated mips64 with kernel 3.2.0 kernel for both mips-linux-gnu and
mips64-n32-linux-gnu.

	[BZ #24699]
	* posix/tst-mmap-offset.c: Mention BZ #24699.
	(do_test_bz21270): Rename to do_test_large_offset and use
	mmap64_maximum_offset to check for maximum expected offset value.
	* sysdeps/generic/mmap_info.h: New file.
	* sysdeps/unix/sysv/linux/mips/mmap_info.h: Likewise.
	* sysdeps/unix/sysv/linux/mmap64.c (MMAP_OFF_HIGH_MASK): Define iff
	__NR_mmap2 is used.

(cherry picked from commit a008c76b56)
2019-07-15 09:24:25 -03:00
Szabolcs Nagy bdd16894aa aarch64: handle STO_AARCH64_VARIANT_PCS
Backport of commit 82bc69c012
and commit 30ba037546
without using DT_AARCH64_VARIANT_PCS for optimizing the symbol table check.
This is needed so the internal abi between ld.so and libc.so is unchanged.

Avoid lazy binding of symbols that may follow a variant PCS with different
register usage convention from the base PCS.

Currently the lazy binding entry code does not preserve all the registers
required for AdvSIMD and SVE vector calls.  Saving and restoring all
registers unconditionally may break existing binaries, even if they never
use vector calls, because of the larger stack requirement for lazy
resolution, which can be significant on an SVE system.

The solution is to mark all symbols in the symbol table that may follow
a variant PCS so the dynamic linker can handle them specially.  In this
patch such symbols are always resolved at load time, not lazily.

So currently LD_AUDIT for variant PCS symbols are not supported, for that
the _dl_runtime_profile entry needs to be changed e.g. to unconditionally
save/restore all registers (but pass down arg and retval registers to
pltentry/exit callbacks according to the base PCS).

This patch also removes a __builtin_expect from the modified code because
the branch prediction hint did not seem useful.

	* sysdeps/aarch64/dl-machine.h (elf_machine_lazy_rel): Check
	STO_AARCH64_VARIANT_PCS and bind such symbols at load time.
2019-07-12 10:14:45 +01:00
Szabolcs Nagy 0b48caab9a aarch64: add STO_AARCH64_VARIANT_PCS and DT_AARCH64_VARIANT_PCS
STO_AARCH64_VARIANT_PCS is a non-visibility st_other flag for marking
symbols that reference functions that may follow a variant PCS with
different register usage convention from the base PCS.

DT_AARCH64_VARIANT_PCS is a dynamic tag that marks ELF modules that
have R_*_JUMP_SLOT relocations for symbols marked with
STO_AARCH64_VARIANT_PCS (i.e. have variant PCS calls via a PLT).

	* elf/elf.h (STO_AARCH64_VARIANT_PCS): Define.
	(DT_AARCH64_VARIANT_PCS): Define.
2019-07-10 15:50:14 +01:00
Florian Weimer 949da7f2fd io: Remove copy_file_range emulation [BZ #24744]
The kernel is evolving this interface (e.g., removal of the
restriction on cross-device copies), and keeping up with that
is difficult.  Applications which need the function should
run kernels which support the system call instead of relying on
the imperfect glibc emulation.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit 5a659ccc0e)
2019-07-09 10:45:47 +02:00
Dmitry V. Levin f056ac8363 libio: do not attempt to free wide buffers of legacy streams [BZ #24228]
Commit a601b74d31 aka glibc-2.23~693
("In preparation for fixing BZ#16734, fix failure in misc/tst-error1-mem
when _G_HAVE_MMAP is turned off.") introduced a regression:
_IO_unbuffer_all now invokes _IO_wsetb to free wide buffers of all
files, including legacy standard files which are small statically
allocated objects that do not have wide buffers and the _mode member,
causing memory corruption.

Another memory corruption in _IO_unbuffer_all happens when -1
is assigned to the _mode member of legacy standard files that
do not have it.

[BZ #24228]
* libio/genops.c (_IO_unbuffer_all)
[SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)]: Do not attempt to free wide
buffers and access _IO_FILE_complete members of legacy libio streams.
* libio/tst-bz24228.c: New file.
* libio/tst-bz24228.map: Likewise.
* libio/Makefile [build-shared] (tests): Add tst-bz24228.
[build-shared] (generated): Add tst-bz24228.mtrace and
tst-bz24228.check.
[run-built-tests && build-shared] (tests-special): Add
$(objpfx)tst-bz24228-mem.out.
(LDFLAGS-tst-bz24228, tst-bz24228-ENV): New variables.
($(objpfx)tst-bz24228-mem.out): New rule.

(cherry picked from commit 21cc130b78)
2019-06-20 17:32:07 +00:00
Dmitry V. Levin 5f90e009b1 NEWS: add entries for bugs 22964, 24180, and 24531 2019-06-20 17:32:07 +00:00
Wilco Dijkstra 54ba8bcd42 Fix tcache count maximum (BZ #24531)
The tcache counts[] array is a char, which has a very small range and thus
may overflow.  When setting tcache_count tunable, there is no overflow check.
However the tunable must not be larger than the maximum value of the tcache
counts[] array, otherwise it can overflow when filling the tcache.

	[BZ #24531]
	* malloc/malloc.c (MAX_TCACHE_COUNT): New define.
	(do_set_tcache_count): Only update if count is small enough.
	* manual/tunables.texi (glibc.malloc.tcache_count): Document max value.

(cherry picked from commit 5ad533e8e6)
2019-05-22 15:00:49 +01:00
Andreas Schwab f9c3c12f33 Fix crash in _IO_wfile_sync (bug 20568)
When computing the length of the converted part of the stdio buffer, use
the number of consumed wide characters, not the (negative) distance to the
end of the wide buffer.

(cherry picked from commit 32ff397533)
2019-05-15 17:26:58 +02:00
Adhemerval Zanella 1961e5c729 elf: Fix pldd (BZ#18035)
Since 9182aa6799 (Fix vDSO l_name for GDB's, BZ#387) the initial link_map
for executable itself and loader will have both l_name and l_libname->name
holding the same value due:

 elf/dl-object.c

 95   new->l_name = *realname ? realname : (char *) newname->name + libname_len - 1;

Since newname->name points to new->l_libname->name.

This leads to pldd to an infinite call at:

 elf/pldd-xx.c

203     again:
204       while (1)
205         {
206           ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);

228           /* Try the l_libname element.  */
229           struct E(libname_list) ln;
230           if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
231             {
232               name_offset = ln.name;
233               goto again;
234             }

Since the value at ln.name (l_libname->name) will be the same as previously
read. The straightforward fix is just avoid the check and read the new list
entry.

I checked also against binaries issues with old loaders with fix for BZ#387,
and pldd could dump the shared objects.

Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu, and
powerpc64le-linux-gnu.

	[BZ #18035]
	* elf/Makefile (tests-container): Add tst-pldd.
	* elf/pldd-xx.c: Use _Static_assert in of pldd_assert.
	(E(find_maps)): Avoid use alloca, use default read file operations
	instead of explicit LFS names, and fix infinite	loop.
	* elf/pldd.c: Explicit set _FILE_OFFSET_BITS, cleanup headers.
	(get_process_info): Use _Static_assert instead of assert, use default
	directory operations instead of explicit LFS names, and free some
	leadek pointers.
	* elf/tst-pldd.c: New file.

(cherry picked from commit 1a4c27355e)
(Backported without the test case due to lack of test-in-container
support.)
2019-04-26 14:06:32 +02:00
TAMUKI Shoichi de9d4aa353 ja_JP locale: Add entry for the new Japanese era [BZ #22964]
The Japanese era name will be changed on May 1, 2019.  The Japanese
government made a preliminary announcement on April 1, 2019.

The glibc ja_JP locale must be updated to include the new era name for
strftime's alternative year format support.

This is a minimal cherry pick of just the required locale changes.

(cherry picked from commit 466afec308)
2019-04-02 23:56:36 -04:00
Stefan Liebler 1ab314d8d3 S390: Mark vx and vxe as important hwcap.
This patch adds vx and vxe as important hwcaps
which allows one to provide shared libraries
tuned for platforms with non-vx/-vxe, vx or vxe.

ChangeLog:

	* sysdeps/s390/dl-procinfo.h (HWCAP_IMPORTANT):
	Add HWCAP_S390_VX and HWCAP_S390_VXE.

(cherry picked from commit 61f5e9470f)
2019-03-21 09:34:00 +01:00
Stefan Liebler 9f44fa22cb Add compiler barriers around modifications of the robust mutex list for pthread_mutex_trylock. [BZ #24180]
While debugging a kernel warning, Thomas Gleixner, Sebastian Sewior and
Heiko Carstens found a bug in pthread_mutex_trylock due to misordered
instructions:
140:   a5 1b 00 01             oill    %r1,1
144:   e5 48 a0 f0 00 00       mvghi   240(%r10),0   <--- THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
14a:   e3 10 a0 e0 00 24       stg     %r1,224(%r10) <--- last THREAD_SETMEM of ENQUEUE_MUTEX_PI

vs (with compiler barriers):
140:   a5 1b 00 01             oill    %r1,1
144:   e3 10 a0 e0 00 24       stg     %r1,224(%r10)
14a:   e5 48 a0 f0 00 00       mvghi   240(%r10),0

Please have a look at the discussion:
"Re: WARN_ON_ONCE(!new_owner) within wake_futex_pi() triggerede"
(https://lore.kernel.org/lkml/20190202112006.GB3381@osiris/)

This patch is introducing the same compiler barriers and comments
for pthread_mutex_trylock as introduced for pthread_mutex_lock and
pthread_mutex_timedlock by commit 8f9450a0b7
"Add compiler barriers around modifications of the robust mutex list."

ChangeLog:

	[BZ #24180]
	* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock):
	Add compiler barriers and comments.

(cherry picked from commit 823624bdc4)
2019-02-07 15:44:18 +01:00
H.J. Lu 2ebadb6451 x86-64 memcmp: Use unsigned Jcc instructions on size [BZ #24155]
Since the size argument is unsigned. we should use unsigned Jcc
instructions, instead of signed, to check size.

Tested on x86-64 and x32, with and without --disable-multi-arch.

	[BZ #24155]
	CVE-2019-7309
	* NEWS: Updated for CVE-2019-7309.
	* sysdeps/x86_64/memcmp.S: Use RDX_LP for size.  Clear the
	upper 32 bits of RDX register for x32.  Use unsigned Jcc
	instructions, instead of signed.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp-2.
	* sysdeps/x86_64/x32/tst-size_t-memcmp-2.c: New test.

(cherry picked from commit 3f635fb433)
2019-02-04 10:23:39 -08:00
H.J. Lu 3a5ae8db68 x86-64 strnlen/wcsnlen: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes strnlen/wcsnlen for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strlen-avx2.S: Use RSI_LP for length.
	Clear the upper 32 bits of RSI register.
	* sysdeps/x86_64/strlen.S: Use RSI_LP for length.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strnlen
	and tst-size_t-wcsnlen.
	* sysdeps/x86_64/x32/tst-size_t-strnlen.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wcsnlen.c: Likewise.

(cherry picked from commit 5165de69c0)
2019-02-01 13:46:20 -08:00
H.J. Lu 2c016ffa24 x86-64 strncpy: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes strncpy for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: Use RDX_LP
	for length.
	* sysdeps/x86_64/multiarch/strcpy-ssse3.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncpy.
	* sysdeps/x86_64/x32/tst-size_t-strncpy.c: New file.

(cherry picked from commit c7c54f65b0)
2019-02-01 13:46:18 -08:00
H.J. Lu d8457edece x86-64 strncmp family: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes the strncmp family for x32.  Tested on x86-64 and x32.
On x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/strcmp-sse42.S: Use RDX_LP for length.
	* sysdeps/x86_64/strcmp.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-strncasecmp,
	tst-size_t-strncmp and tst-size_t-wcsncmp.
	* sysdeps/x86_64/x32/tst-size_t-strncasecmp.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-strncmp.c: Likewise.
	* sysdeps/x86_64/x32/tst-size_t-wcsncmp.c: Likewise.

(cherry picked from commit ee915088a0)
2019-02-01 13:45:34 -08:00
H.J. Lu 55f8812858 x86-64 memset/wmemset: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memset/wmemset for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memset-avx512-no-vzeroupper.S: Use
	RDX_LP for length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-wmemset.
	* sysdeps/x86_64/x32/tst-size_t-memset.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wmemset.c: Likewise.

(cherry picked from commit 82d0b4a4d7)
2019-02-01 13:32:05 -08:00
H.J. Lu efc3714845 x86-64 memrchr: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memrchr for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/memrchr.S: Use RDX_LP for length.
	* sysdeps/x86_64/multiarch/memrchr-avx2.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memrchr.
	* sysdeps/x86_64/x32/tst-size_t-memrchr.c: New file.

(cherry picked from commit ecd8b842cf)
2019-02-01 13:20:12 -08:00
H.J. Lu a4690969ed x86-64 memcpy: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memcpy for x32.  Tested on x86-64 and x32.  On x86-64,
libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memcpy-ssse3-back.S: Use RDX_LP for
	length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memcpy-ssse3.S: Likewise.
	* sysdeps/x86_64/multiarch/memmove-avx512-no-vzeroupper.S:
	Likewise.
	* sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:
	Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcpy.
	tst-size_t-wmemchr.
	* sysdeps/x86_64/x32/tst-size_t-memcpy.c: New file.

(cherry picked from commit 231c56760c)
2019-02-01 13:02:18 -08:00
H.J. Lu 6465327195 x86-64 memcmp/wmemcmp: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memcmp/wmemcmp for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/multiarch/memcmp-avx2-movbe.S: Use RDX_LP for
	length.  Clear the upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memcmp-sse4.S: Likewise.
	* sysdeps/x86_64/multiarch/memcmp-ssse3.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memcmp and
	tst-size_t-wmemcmp.
	* sysdeps/x86_64/x32/tst-size_t-memcmp.c: New file.
	* sysdeps/x86_64/x32/tst-size_t-wmemcmp.c: Likewise.

(cherry picked from commit b304fc201d)
2019-02-01 12:54:55 -08:00
H.J. Lu 50117e00a1 x86-64 memchr/wmemchr: Properly handle the length parameter [BZ #24097]
On x32, the size_t parameter may be passed in the lower 32 bits of a
64-bit register with the non-zero upper 32 bits.  The string/memory
functions written in assembly can only use the lower 32 bits of a
64-bit register as length or must clear the upper 32 bits before using
the full 64-bit register for length.

This pach fixes memchr/wmemchr for x32.  Tested on x86-64 and x32.  On
x86-64, libc.so is the same with and withou the fix.

	[BZ #24097]
	CVE-2019-6488
	* sysdeps/x86_64/memchr.S: Use RDX_LP for length.  Clear the
	upper 32 bits of RDX register.
	* sysdeps/x86_64/multiarch/memchr-avx2.S: Likewise.
	* sysdeps/x86_64/x32/Makefile (tests): Add tst-size_t-memchr and
	tst-size_t-wmemchr.
	* sysdeps/x86_64/x32/test-size_t.h: New file.
	* sysdeps/x86_64/x32/tst-size_t-memchr.c: Likewise.
	* sysdeps/x86_64/x32/tst-size_t-wmemchr.c: Likewise.

(cherry picked from commit 97700a34f3)
2019-02-01 12:54:39 -08:00
Dmitry V. Levin 68c2930a56 NEWS: add entries for bugs 23275, 23861, and 23907 2019-01-06 00:31:53 +00:00
Florian Weimer 766e8fb932 intl: Do not return NULL on asprintf failure in gettext [BZ #24018]
Fixes commit 9695dd0c93 ("DCIGETTEXT:
Use getcwd, asprintf to construct absolute pathname").

(cherry picked from commit 8c1aafc1f3)
2019-01-02 17:11:31 +01:00
Florian Weimer 3981fc3453 malloc: Always call memcpy in _int_realloc [BZ #24027]
This commit removes the custom memcpy implementation from _int_realloc
for small chunk sizes.  The ncopies variable has the wrong type, and
an integer wraparound could cause the existing code to copy too few
elements (leaving the new memory region mostly uninitialized).
Therefore, removing this code fixes bug 24027.

(cherry picked from commit b50dd3bc8c)
2019-01-01 10:48:37 +01:00
Andreas Schwab f6d0e8c36f Fix rwlock stall with PREFER_WRITER_NONRECURSIVE_NP (bug 23861)
In the read lock function (__pthread_rwlock_rdlock_full) there was a
code path which would fail to reload __readers while waiting for
PTHREAD_RWLOCK_RWAITING to change. This failure to reload __readers
into a local value meant that various conditionals used the old value
of __readers and with only two threads left it could result in an
indefinite stall of one of the readers (waiting for PTHREAD_RWLOCK_RWAITING
to go to zero, but it never would).

(cherry picked from commit f21e8f8ca4)
2018-12-13 12:02:57 -05:00
Tulio Magno Quites Machado Filho 2794474c65 powerpc: Add missing CFI register information (bug #23614)
Add CFI information about the offset of registers stored in the stack
frame.

	[BZ #23614]
	* sysdeps/powerpc/powerpc64/addmul_1.S (FUNC): Add CFI offset for
	registers saved in the stack frame.
	* sysdeps/powerpc/powerpc64/lshift.S (__mpn_lshift): Likewise.
	* sysdeps/powerpc/powerpc64/mul_1.S (__mpn_mul_1): Likewise.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Reviewed-by: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
(cherry picked from commit 1d880d4a9b)
2018-12-13 09:32:29 +01:00
Tulio Magno Quites Machado Filho d8ca7a0c71 Fix _dl_profile_fixup data-dependency issue (Bug 23690)
There is a data-dependency between the fields of struct l_reloc_result
and the field used as the initialization guard. Users of the guard
expect writes to the structure to be observable when they also observe
the guard initialized. The solution for this problem is to use an acquire
and release load and store to ensure previous writes to the structure are
observable if the guard is initialized.

The previous implementation used DL_FIXUP_VALUE_ADDR (l_reloc_result->addr)
as the initialization guard, making it impossible for some architectures
to load and store it atomically, i.e. hppa and ia64, due to its larger size.

This commit adds an unsigned int to l_reloc_result to be used as the new
initialization guard of the struct, making it possible to load and store
it atomically in all architectures. The fix ensures that the values
observed in l_reloc_result are consistent and do not lead to crashes.
The algorithm is documented in the code in elf/dl-runtime.c
(_dl_profile_fixup). Not all data races have been eliminated.

Tested with build-many-glibcs and on powerpc, powerpc64, and powerpc64le.

	[BZ #23690]
	* elf/dl-runtime.c (_dl_profile_fixup): Guarantee memory
	modification order when accessing reloc_result->addr.
	* include/link.h (reloc_result): Add field init.
	* nptl/Makefile (tests): Add tst-audit-threads.
	(modules-names): Add tst-audit-threads-mod1 and
	tst-audit-threads-mod2.
	Add rules to build tst-audit-threads.
	* nptl/tst-audit-threads-mod1.c: New file.
	* nptl/tst-audit-threads-mod2.c: Likewise.
	* nptl/tst-audit-threads.c: Likewise.
	* nptl/tst-audit-threads.h: Likewise.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e5d262effe)
2018-12-13 06:41:41 +01:00
Florian Weimer f1e211096b inet/tst-if_index-long: New test case for CVE-2018-19591 [BZ #23927]
(cherry picked from commit 899478c2bf)
2018-12-12 13:25:11 +01:00
Florian Weimer 4e9f34e54f support: Implement <support/descriptors.h> to track file descriptors
(cherry picked from commit f255336a93)
2018-12-12 13:25:07 +01:00
Florian Weimer e75481a7a7 support: Close original descriptors in support_capture_subprocess
(cherry picked from commit 02cd5c1a8d)
2018-12-12 13:24:40 +01:00
Florian Weimer 0f79dc0be3 support_quote_string: Do not use str parameter name
This avoids a build failure if this identifier is used as a macro
in a test.

(cherry picked from commit 47d8d9a217)
2018-12-12 13:24:40 +01:00
Florian Weimer 6b2dd53aa0 support: Implement support_quote_string
Reviewed-by: Jonathan Nieder <jrnieder@gmail.com>
(cherry picked from commit c74a91deaa)
2018-12-12 13:24:38 +01:00
DJ Delorie 50477165b9 malloc: Add another test for tcache double free check.
This one tests for BZ#23907 where the double free
test didn't check the tcache bin bounds before dereferencing
the bin.

[BZ #23907]
* malloc/tst-tcfree3.c: New.
* malloc/Makefile: Add it.

(cherry picked from commit 7c9a7c6836)
2018-12-12 13:23:48 +01:00
DJ Delorie 4b246928bd malloc: tcache double free check
* malloc/malloc.c (tcache_entry): Add key field.
(tcache_put): Set it.
(tcache_get): Likewise.
(_int_free): Check for double free in tcache.
* malloc/tst-tcfree1.c: New.
* malloc/tst-tcfree2.c: New.
* malloc/Makefile: Run the new tests.
* manual/probes.texi: Document memory_tcache_double_free probe.

* dlfcn/dlerror.c (check_free): Prevent double frees.

(cherry picked from commit bcdaad21d4)

malloc: tcache: Validate tc_idx before checking for double-frees [BZ #23907]

The previous check could read beyond the end of the tcache entry
array.  If the e->key == tcache cookie check happened to pass, this
would result in crashes.

(cherry picked from commit affec03b71)
2018-12-12 13:22:42 +01:00
Florian Weimer 9f433fc791 CVE-2018-19591: if_nametoindex: Fix descriptor for overlong name [BZ #23927]
(cherry picked from commit d527c860f5)
2018-11-27 21:26:02 +01:00
Alexandra Hájková 1517dfb8aa Add an additional test to resolv/tst-resolv-network.c
Test for the infinite loop in getnetbyname, bug #17630.

(cherry picked from commit ac8060265b)
2018-11-09 14:39:11 +01:00
Andreas Schwab 1050634904 libanl: properly cleanup if first helper thread creation failed (bug 22927)
(cherry picked from commit bd3b0fbae3)
2018-11-06 17:11:25 +01:00
Adhemerval Zanella d8eee5ef55 x86: Fix Haswell CPU string flags (BZ#23709)
Th commit 'Disable TSX on some Haswell processors.' (2702856bf4) changed the
default flags for Haswell models.  Previously, new models were handled by the
default switch path, which assumed a Core i3/i5/i7 if AVX is available. After
the patch, Haswell models (0x3f, 0x3c, 0x45, 0x46) do not set the flags
Fast_Rep_String, Fast_Unaligned_Load, Fast_Unaligned_Copy, and
Prefer_PMINUB_for_stringop (only the TSX one).

This patch fixes it by disentangle the TSX flag handling from the memory
optimization ones.  The strstr case cited on patch now selects the
__strstr_sse2_unaligned as expected for the Haswell cpu.

Checked on x86_64-linux-gnu.

	[BZ #23709]
	* sysdeps/x86/cpu-features.c (init_cpu_features): Set TSX bits
	independently of other flags.

(cherry picked from commit c3d8dc45c9)
2018-11-02 11:14:57 +01:00
Szabolcs Nagy 5cd5309d91 i64: fix missing exp2f, log2f and powf symbols in libm.a [BZ #23822]
When new symbol versions were introduced without SVID compatible
error handling the exp2f, log2f and powf symbols were accidentally
removed from the ia64 lim.a.  The regression was introduced by
the commits

f5f0f52651
New expf and exp2f version without SVID compat wrapper

72d3d28108
New symbol version for logf, log2f and powf without SVID compat

With WEAK_LIBM_ENTRY(foo), there is a hidden __foo and weak foo
symbol definition in both SHARED and !SHARED build.

	[BZ #23822]
	* sysdeps/ia64/fpu/e_exp2f.S (exp2f): Use WEAK_LIBM_ENTRY.
	* sysdeps/ia64/fpu/e_log2f.S (log2f): Likewise.
	* sysdeps/ia64/fpu/e_exp2f.S (powf): Likewise.

(cherry picked from commit ba5b14c761)
2018-10-26 15:50:54 +01:00
Florian Weimer 1759ea197b conform: XFAIL siginfo_t si_band test on sparc64
We can use long int on sparcv9, but on sparc64, we must match the int
type used by the kernel (and not long int, as in POSIX).

(cherry picked from commit 7c5e34d7f1)
2018-10-26 09:25:48 +02:00
Ilya Yu. Malakhov 77b4b8231e signal: Use correct type for si_band in siginfo_t [BZ #23562]
(cherry picked from commit f997b4be18)
2018-10-22 13:16:08 +02:00
Stefan Liebler 5bdb6897fc Fix race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP [BZ #23275]
The race leads either to pthread_mutex_destroy returning EBUSY
or triggering an assertion (See description in bugzilla).

This patch is fixing the race by ensuring that the elision path is
used in all cases if elision is enabled by the GLIBC_TUNABLES framework.

The __kind variable in struct __pthread_mutex_s is accessed concurrently.
Therefore we are now using the atomic macros.

The new testcase tst-mutex10 is triggering the race on s390x and intel.
Presumably also on power, but I don't have access to a power machine
with lock-elision. At least the code for power is the same as on the other
two architectures.

ChangeLog:

	[BZ #23275]
	* nptl/tst-mutex10.c: New File.
	* nptl/Makefile (tests): Add tst-mutex10.
	(tst-mutex10-ENV): New variable.
	* sysdeps/unix/sysv/linux/s390/force-elision.h: (FORCE_ELISION):
	Ensure that elision path is used if elision is available.
	* sysdeps/unix/sysv/linux/powerpc/force-elision.h (FORCE_ELISION):
	Likewise.
	* sysdeps/unix/sysv/linux/x86/force-elision.h: (FORCE_ELISION):
	Likewise.
	* nptl/pthreadP.h (PTHREAD_MUTEX_TYPE, PTHREAD_MUTEX_TYPE_ELISION)
	(PTHREAD_MUTEX_PSHARED): Use atomic_load_relaxed.
	* nptl/pthread_mutex_consistent.c (pthread_mutex_consistent): Likewise.
	* nptl/pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling):
	Likewise.
	* nptl/pthread_mutex_lock.c (__pthread_mutex_lock_full)
	(__pthread_mutex_cond_lock_adjust): Likewise.
	* nptl/pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling):
	Likewise.
	* nptl/pthread_mutex_timedlock.c (__pthread_mutex_timedlock): Likewise.
	* nptl/pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
	* nptl/pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Likewise.
	* sysdeps/nptl/bits/thread-shared-types.h (struct __pthread_mutex_s):
	Add comments.
	* nptl/pthread_mutex_destroy.c (__pthread_mutex_destroy):
	Use atomic_load_relaxed and atomic_store_relaxed.
	* nptl/pthread_mutex_init.c (__pthread_mutex_init):
	Use atomic_store_relaxed.

(cherry picked from commit 403b4feb22)
2018-10-18 12:35:00 +02:00
Adhemerval Zanella a127df9f3e Fix misreported errno on preadv2/pwritev2 (BZ#23579)
The fallback code of Linux wrapper for preadv2/pwritev2 executes
regardless of the errno code for preadv2, instead of the case where
the syscall is not supported.

This fixes it by calling the fallback code iff errno is ENOSYS. The
patch also adds tests for both invalid file descriptor and invalid
iov_len and vector count.

The only discrepancy between preadv2 and fallback code regarding
error reporting is when an invalid flags are used.  The fallback code
bails out earlier with ENOTSUP instead of EINVAL/EBADF when the syscall
is used.

Checked on x86_64-linux-gnu on a 4.4.0 and 4.15.0 kernel.

	[BZ #23579]
	* misc/tst-preadvwritev2-common.c (do_test_with_invalid_fd): New
	test.
	* misc/tst-preadvwritev2.c, misc/tst-preadvwritev64v2.c (do_test):
	Call do_test_with_invalid_fd.
	* sysdeps/unix/sysv/linux/preadv2.c (preadv2): Use fallback code iff
	errno is ENOSYS.
	* sysdeps/unix/sysv/linux/preadv64v2.c (preadv64v2): Likewise.
	* sysdeps/unix/sysv/linux/pwritev2.c (pwritev2): Likewise.
	* sysdeps/unix/sysv/linux/pwritev64v2.c (pwritev64v2): Likewise.

(cherry picked from commit 7a16bdbb9f)
2018-09-28 15:30:30 -03:00
Florian Weimer 3b3775697a preadv2/pwritev2: Handle offset == -1 [BZ #22753]
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>

(cherry picked from commit d4b4a00a46)
2018-09-28 15:15:06 -03:00
Stefan Liebler 9533f19aa5 Fix segfault in maybe_script_execute.
If glibc is built with gcc 8 and -march=z900,
the testcase posix/tst-spawn4-compat crashes with a segfault.

In function maybe_script_execute, the new_argv array is dynamically
initialized on stack with (argc + 1) elements.
The function wants to add _PATH_BSHELL as the first argument
and writes out of bounds of new_argv.
There is an off-by-one because maybe_script_execute fails to count
the terminating NULL when sizing new_argv.

ChangeLog:

	* sysdeps/unix/sysv/linux/spawni.c (maybe_script_execute):
	Increment size of new_argv by one.

(cherry picked from commit 28669f86f6)
2018-09-10 14:25:47 +02:00
Martin Kuchta 2b47bb9cba pthread_cond_broadcast: Fix waiters-after-spinning case [BZ #23538]
(cherry picked from commit 99ea93ca31)
2018-08-27 19:09:50 +02:00
H.J. Lu 2dab17550d x86: Populate COMMON_CPUID_INDEX_80000001 for Intel CPUs [BZ #23459]
Reviewed-by: Carlos O'Donell <carlos@redhat.com>

	[BZ #23459]
	* sysdeps/x86/cpu-features.c (get_extended_indices): New
	function.
	(init_cpu_features): Call get_extended_indices for both Intel
	and AMD CPUs.
	* sysdeps/x86/cpu-features.h (COMMON_CPUID_INDEX_80000001):
	Remove "for AMD" comment.

(cherry picked from commit be525a69a6)
2018-07-29 06:30:59 -07:00
H.J. Lu a452341529 x86: Correct index_cpu_LZCNT [BZ #23456]
cpu-features.h has

 #define bit_cpu_LZCNT		(1 << 5)
 #define index_cpu_LZCNT	COMMON_CPUID_INDEX_1
 #define reg_LZCNT

But the LZCNT feature bit is in COMMON_CPUID_INDEX_80000001:

Initial EAX Value: 80000001H
ECX Extended Processor Signature and Feature Bits:
Bit 05: LZCNT available

index_cpu_LZCNT should be COMMON_CPUID_INDEX_80000001, not
COMMON_CPUID_INDEX_1.  The VMX feature bit is in COMMON_CPUID_INDEX_1:

Initial EAX Value: 01H
Feature Information Returned in the ECX Register:
5 VMX

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

	[BZ #23456]
	* sysdeps/x86/cpu-features.h (index_cpu_LZCNT): Set to
	COMMON_CPUID_INDEX_80000001.

(cherry picked from commit 65d87ade1e)
2018-07-29 06:30:59 -07:00
Rafal Luzynski 8623cfe300 NEWS: Mention bug 22996.
The fix has been backported in the commit
718445e569.
2018-07-12 00:25:41 +02:00
Florian Weimer 68c1bf8097 regexec: Fix off-by-one bug in weight comparison [BZ #23036]
Each weight is prefixed by its length, and the length does not include
itself in the count.  This can be seen clearly from the find_idx
function in string/strxfrm_l.c, for example.  The old code behaved as if
the length itself counted, thus comparing an additional byte after the
weight, leading to spurious comparison failures and incorrect further
partitioning of character equivalence classes.

(cherry picked from commit 7b2f4cedf0)
2018-07-11 16:43:17 +02:00
Sylvain Lesage 718445e569 es_BO locale: Change LC_PAPER to en_US (bug 22996).
[BZ #22996]
	* localedata/locales/es_BO (LC_PAPER): Change to “copy "en_US"”.

(cherry picked from commit cdb52c7182)
2018-07-07 17:20:57 +02:00
Florian Weimer 33d1bde2de conform/conformtest.pl: Escape literal braces in regular expressions
This suppresses Perl warnings like these:

Unescaped left brace in regex is deprecated here (and will be fatal in
Perl 5.32), passed through in regex; marked by <-- HERE in m/^element
*({ <-- HERE ([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*)
*(.*)/ at conformtest.pl line 370.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit ddb3c626b0)
2018-07-06 16:40:22 +02:00
Florian Weimer 5fab7fe1dc math: Set 387 and SSE2 rounding mode for tgamma on i386 [BZ #23253]
Previously, only the SSE2 rounding mode was set, so the assembler
implementations using 387 were not following the expecting rounding
mode.

(cherry picked from commit f496b28e61)
2018-07-04 12:01:31 +02:00
Florian Weimer 7602b9e48c stdio-common/tst-printf.c: Remove part under a non-free license [BZ #23363]
The license does not allow modification.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 5a35750665)
2018-07-03 18:36:19 +02:00
Florian Weimer 4492721165 libio: Add tst-vtables, tst-vtables-interposed
(cherry picked from commit 29055464a0)

Some adjustments were needed for a tricky multi-inclusion issue related
to libioP.h.
2018-07-03 17:57:14 +02:00
Florian Weimer 060eb7c3b5 Synchronize support/ infrastructure with master
This commit updates the support/ subdirectory to
commit 5c0202af4b
on the master branch.
2018-07-03 17:42:59 +02:00
Florian Weimer 3bb7482574 libio: Disable vtable validation in case of interposition [BZ #23313]
(cherry picked from commit c402355dfa)
2018-07-03 15:54:49 +02:00
Daniel Alvarez 4476d16b03 getifaddrs: Don't return ifa entries with NULL names [BZ #21812]
A lookup operation in map_newlink could turn into an insert because of
holes in the interface part of the map.  This leads to incorrectly set
the name of the interface to NULL when the interface is not present
for the address being processed (most likely because the interface was
added between the RTM_GETLINK and RTM_GETADDR calls to the kernel).
When such changes are detected by the kernel, it'll mark the dump as
"inconsistent" by setting NLM_F_DUMP_INTR flag on the next netlink
message.

This patch checks this condition and retries the whole operation.
Hopes are that next time the interface corresponding to the address
entry is present in the list and correct name is returned.

(cherry picked from commit c1f86a33ca)
2018-06-29 17:23:52 +02:00
Florian Weimer 4e0847afce Use _STRUCT_TIMESPEC as guard in <bits/types/struct_timespec.h> [BZ #23349]
After commit d76d370355 ("Fix missing
timespec definition for sys/stat.h (BZ #21371)") in combination with
kernel UAPI changes, GCC sanitizer builds start to fail due to a
conflicting definition of struct timespec in <linux/time.h>.  Use
_STRUCT_TIMESPEC as the header file inclusion guard, which is already
checked in the kernel header, to support including <linux/time.h> and
<sys/stat.h> in the same translation unit.

(cherry picked from commit c1c2848b57)
2018-06-28 13:21:20 +02:00
Gabriel F. T. Gomes ffc5623978 Fix parameter type in C++ version of iseqsig (bug 23171)
The commit

  commit c85e54ac6c
  Author: Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
  Date:   Fri Nov 3 10:44:36 2017 -0200

      Provide a C++ version of iseqsig (bug 22377)

mistakenly used double parameters in the long double version of iseqsig,
thus causing spurious conversions to double, as reported on bug 23171.

Tested for powerpc64le and x86_64.

(cherry picked from commit fb0e10b8eb)
2018-06-19 13:50:46 -03:00
Carlos O'Donell 80c83e9114 Improve DST handling (Bug 23102, Bug 21942, Bug 18018, Bug 23259).
This commit improves DST handling significantly in the following
ways: firstly is_dst () is overhauled to correctly process DST
sequences that would be accepted given the ELF gABI.  This means that
we actually now accept slightly more sequences than before.  Now we
accept $ORIGIN$ORIGIN, but in the past we accepted only $ORIGIN\0 or
$ORIGIN/..., but this kind of behaviour results in unexpected
and uninterpreted DST sequences being used as literal search paths
leading to security defects.  Therefore the first step in correcting
this defect is making is_dst () properly account for all DSTs
and making the function context free in the sense that it counts
DSTs without knowledge of path, or AT_SECURE.  Next, _dl_dst_count ()
is also simplified to count all DSTs regardless of context.
Then in _dl_dst_substitute () we reintroduce context-dependent
processing for such things as AT_SECURE handling.  At the level of
_dl_dst_substitute we can have access to things like the true start
of the string sequence to validate $ORIGIN-based paths rooted in
trusted directories.  Lastly, we tighten up the accepted sequences
in AT_SECURE, and avoid leaving known unexpanded DSTs, this is
noted in the NEWS entry.

Verified with a sequence of 68 tests on x86_64 that cover
non-AT_SECURE and AT_SECURE testing using a sysroot (requires root
to run).  The tests cover cases for bug 23102, bug 21942, bug 18018,
and bug 23259.  These tests are not yet appropriate for the glibc
regression testsuite, but with the upcoming test-in-container testing
framework it should be possible to include these tests upstream soon.

See the mailing list for the tests:
https://www.sourceware.org/ml/libc-alpha/2018-06/msg00251.html

(cherry picked from commit 5aad5f6178)
2018-06-18 13:41:00 +02:00
Florian Weimer b25e5e3c09 x86: Make strncmp usable from rtld
Due to the way the conditions were written, the rtld build of strncmp
ended up with no definition of the strncmp symbol at all: The
implementations were renamed for use within an IFUNC resolver, but the
IFUNC resolver itself was missing (because rtld does not use IFUNCs).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e826574c98)
2018-06-18 13:41:00 +02:00
Florian Weimer 8308fb2182 math: Update i686 ulps
The results are from configuring with and without
--disable-multi-arch,  building with “-march=x86-64 -mtune=generic
-mfpmath=sse” and running the testsuite on a Haswell-era CPU.

Slightly higher ulps are required than in master (commit
e02c026f38).
2018-06-18 13:40:29 +02:00
Adhemerval Zanella 4a87157435 Mention BZ#23264 in NEWS 2018-06-08 18:14:46 -03:00
Adhemerval Zanella 78e48cb5e5 posix: Fix posix_spawnp to not execute invalid binaries in non compat mode (BZ#23264)
Current posix_spawnp implementation wrongly tries to execute invalid
binaries (for instance script without shebang) as a shell script in
non compat mode.  It was a regression introduced by
9ff72da471 when __spawni started to use
__execvpe instead of __execve (glibc __execvpe try to execute ENOEXEC
as shell script regardless).

This patch fixes it by using an internal symbol (__execvpex) with the
faulty semantic (since compat mode is handled by spawni.c itself).

It was reported by Daniel Drake on libc-help [1].

Checked on x86_64-linux-gnu and i686-linux-gnu.

	[BZ #23264]
	* include/unistd.h (__execvpex): New prototype.
	* posix/Makefile (tests): Add tst-spawn4.
	(tests-internal): Add tst-spawn4-compat.
	* posix/execvpe.c (__execvpe_common, __execvpex): New functions.
	* posix/tst-spawn4-compat.c: New file.
	* posix/tst-spawn4.c: Likewise.
	* sysdeps/unix/sysv/linux/spawni.c (__spawni): Do not interpret invalid
	binaries as shell scripts.
	* sysdeps/posix/spawni.c (__spawni): Likewise.

[1] https://sourceware.org/ml/libc-help/2018-06/msg00012.html

(cherry picked from commit 283d985122)
2018-06-08 17:34:01 -03:00
Florian Weimer 0262507918 libio: Avoid _allocate_buffer, _free_buffer function pointers [BZ #23236]
These unmangled function pointers reside on the heap and could
be targeted by exploit writers, effectively bypassing libio vtable
validation.  Instead, we ignore these pointers and always call
malloc or free.

In theory, this is a backwards-incompatible change, but using the
global heap instead of the user-supplied callback functions should
have little application impact.  (The old libstdc++ implementation
exposed this functionality via a public, undocumented constructor
in its strstreambuf class.)

(cherry picked from commit 4e8a6346cd)
2018-06-01 10:43:06 +02:00
Florian Weimer 6c99e37f6f NEWS: Move security-lated changes before bug list
This matches the practice for previous releases.
2018-05-24 15:50:29 +02:00
Florian Weimer 50df56ca86 Add references to CVE-2018-11236, CVE-2017-18269 2018-05-24 14:41:57 +02:00
H.J. Lu 0cf8a53e5f Add a test case for [BZ #23196]
[BZ #23196]
	* string/test-memcpy.c (do_test1): New function.
	(test_main): Call it.

(cherry picked from commit ed983107bb)
2018-05-24 14:39:41 +02:00
Andreas Schwab f51c836768 Don't write beyond destination in __mempcpy_avx512_no_vzeroupper (bug 23196)
When compiled as mempcpy, the return value is the end of the destination
buffer, thus it cannot be used to refer to the start of it.

(cherry picked from commit 9aaaab7c6e)
2018-05-24 14:39:18 +02:00
Florian Weimer 0cd4a5e87f sunrpc: Remove stray exports without --enable-obsolete-rpc [BZ #23166]
This is needed to avoid a warning when linking against libtirpc:

/lib64/libc.so.6: warning: common of `rpc_createerr@@TIRPC_0.3.0' overridden by definition
/usr/lib64/libtirpc.so: warning: defined here

This ld warning is not enabled by default; -Wl,--warn-common enables it.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

(cherry picked from commit 89aacb513e)
2018-05-15 08:21:11 +02:00
Rafal Luzynski 8af3185d3e gd_GB: Fix typo in abbreviated "May" (bug 23152).
[BZ #23152]
	* localedata/locales/gd_GB (abmon): Fix typo in May:
	"Mhàrt" -> "Cèit".  Adjust the comment according to the change.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit bb066cb806)
2018-05-11 12:13:08 +00:00
Dmitry V. Levin b2dd29a7ca NEWS: add entries for bugs 17343, 20419, 22644, 22786, 22884, 22947, 23005, 23037, 23069, 23137 2018-05-10 10:56:25 +00:00
Paul Pluzhnikov f19e67884c Fix path length overflow in realpath [BZ #22786]
Integer addition overflow may cause stack buffer overflow
when realpath() input length is close to SSIZE_MAX.

2018-05-09  Paul Pluzhnikov  <ppluzhnikov@google.com>

	[BZ #22786]
	* stdlib/canonicalize.c (__realpath): Fix overflow in path length
	computation.
	* stdlib/Makefile (test-bz22786): New test.
	* stdlib/test-bz22786.c: New test.

(cherry picked from commit 5460617d15)
2018-05-10 10:56:25 +00:00
Paul Pluzhnikov edbf537d07 Fix stack overflow with huge PT_NOTE segment [BZ #20419]
A PT_NOTE in a binary could be arbitratily large, so using alloca
for it may cause stack overflow.  If the note is larger than
__MAX_ALLOCA_CUTOFF, use dynamically allocated memory to read it in.

2018-05-05  Paul Pluzhnikov  <ppluzhnikov@google.com>

	[BZ #20419]
	* elf/dl-load.c (open_verify): Fix stack overflow.
	* elf/Makefile (tst-big-note): New test.
	* elf/tst-big-note-lib.S: New.
	* elf/tst-big-note.c: New.

(cherry picked from commit 0065aaaaae)
2018-05-10 10:56:25 +00:00
Stefan Liebler db988e50a8 Fix blocking pthread_join. [BZ #23137]
On s390 (31bit) if glibc is build with -Os, pthread_join sometimes
blocks indefinitely. This is e.g. observable with
testcase intl/tst-gettext6.

pthread_join is calling lll_wait_tid(tid), which performs the futex-wait
syscall in a loop as long as tid != 0 (thread is alive).

On s390 (and build with -Os), tid is loaded from memory before
comparing against zero and then the tid is loaded a second time
in order to pass it to the futex-wait-syscall.
If the thread exits in between, then the futex-wait-syscall is
called with the value zero and it waits until a futex-wake occurs.
As the thread is already exited, there won't be a futex-wake.

In lll_wait_tid, the tid is stored to the local variable __tid,
which is then used as argument for the futex-wait-syscall.
But unfortunately the compiler is allowed to reload the value
from memory.

With this patch, the tid is loaded with atomic_load_acquire.
Then the compiler is not allowed to reload the value for __tid from memory.

ChangeLog:

	[BZ #23137]
	* sysdeps/nptl/lowlevellock.h (lll_wait_tid):
	Use atomic_load_acquire to load __tid.

(cherry picked from commit 1660901840)
2018-05-10 10:56:25 +00:00
Joseph Myers a06d48fb9f Add PTRACE_SECCOMP_GET_METADATA from Linux 4.16 to sys/ptrace.h.
This patch adds the PTRACE_SECCOMP_GET_METADATA constant from Linux
4.16 to all relevant sys/ptrace.h files.  A type struct
__ptrace_seccomp_metadata, analogous to other such types, is also
added.

Tested for x86_64, and with build-many-glibcs.py.

	* sysdeps/unix/sysv/linux/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): New enum value and macro.
	* sysdeps/unix/sysv/linux/bits/ptrace-shared.h
	(struct __ptrace_seccomp_metadata): New type.
	* sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/arm/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/ia64/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/s390/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/sparc/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/tile/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.
	* sysdeps/unix/sysv/linux/x86/sys/ptrace.h
	(PTRACE_SECCOMP_GET_METADATA): Likewise.

(cherry picked from commit 9320ca88a1)
2018-05-10 10:56:25 +00:00
Florian Weimer c550fff3b7 resolv: Fully initialize struct mmsghdr in send_dg [BZ #23037]
(cherry picked from commit 583a27d525)
2018-05-10 10:56:25 +00:00
Florian Weimer 11dee02dc0 manual: Various fixes to the mbstouwcs example, and mbrtowc update
The example did not work because the null byte was not converted, and
mbrtowc was called with a zero-length input string.  This results in a
(size_t) -2 return value, so the function always returns NULL.

The size computation for the heap allocation of the result was
incorrect because it did not deal with integer overflow.

Error checking was missing, and the allocated memory was not freed on
error paths.  All error returns now set errno.  (Note that there is an
assumption that free does not clobber errno.)

The slightly unportable comparision against (size_t) -2 to catch both
(size_t) -1 and (size_t) -2 return values is gone as well.

A null wide character needs to be stored in the result explicitly, to
terminate it.

The description in the manual is updated to deal with these finer
points.  The (size_t) -2 behavior (consuming the input bytes) matches
what is specified in ISO C11.

(cherry picked from commit cf138b0c83)
(cherry picked from commit 690c3475f1)
2018-05-10 10:56:25 +00:00
Florian Weimer 3ca9a9aeea manual: Move mbstouwcs to an example C file
(cherry picked from commit 0f33925269)
2018-05-10 10:56:25 +00:00
H.J. Lu d658d6d757 Update RWF_SUPPORTED for Linux kernel 4.16 [BZ #22947]
Add RWF_APPEND to RWF_SUPPORTED to support Linux kernel 4.16.

	[BZ #22947]
	* bits/uio-ext.h (RWF_APPEND): New.
	* sysdeps/unix/sysv/linux/bits/uio-ext.h (RWF_APPEND): Likewise.
	* manual/llio.texi: Document RWF_APPEND.
	* misc/tst-preadvwritev2-common.c (RWF_APPEND): New.
	(RWF_SUPPORTED): Add RWF_APPEND.

(cherry picked from commit f2652643d7)
2018-05-10 10:56:25 +00:00
Jesse Hathaway a8a7d4c5d8 getlogin_r: return early when linux sentinel value is set
When there is no login uid Linux sets /proc/self/loginid to the sentinel
value of, (uid_t) -1. If this is set we can return early and avoid
needlessly looking up the sentinel value in any configured nss
databases.

Checked on aarch64-linux-gnu.

	* sysdeps/unix/sysv/linux/getlogin_r.c (__getlogin_r_loginuid): Return
	early when linux sentinel value is set.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
(cherry picked from commit cc8a1620eb)
2018-05-10 10:56:25 +00:00
Andreas Schwab 1a90f09f24 Fix crash in resolver on memory allocation failure (bug 23005)
(cherry picked from commit f178e59fa5)
2018-05-10 10:56:25 +00:00
Joseph Myers 36fed309f6 Fix signed integer overflow in random_r (bug 17343).
Bug 17343 reports that stdlib/random_r.c has code with undefined
behavior because of signed integer overflow on int32_t.  This patch
changes the code so that the possibly overflowing computations use
unsigned arithmetic instead.

Note that the bug report refers to "Most code" in that file.  The
places changed in this patch are the only ones I found where I think
such overflow can occur.

Tested for x86_64 and x86.

	[BZ #17343]
	* stdlib/random_r.c (__random_r): Use unsigned arithmetic for
	possibly overflowing computations.

(cherry picked from commit 8a07b0c43c)
2018-05-10 10:56:25 +00:00
Aurelien Jarno 623f4aef13 Add tst-sigaction.c to test BZ #23069
This simple test uses sigaction to define a signal handler. It then
uses sigaction again to fetch the information about the same signal
handler, and check that they are consistent. This is enough to detect
mismatches between struct kernel_sigaction and the kernel version of
struct sigaction, like in BZ #23069.

Changelog:
       * signal/tst-sigaction.c: New file to test BZ #23069.
       * signal/Makefile (tests): Fix indentation. Add tst-sigaction.

(cherry picked from commit 7a6f747871)
2018-04-28 13:18:25 +02:00
Aurelien Jarno ced2cd1ede RISC-V: fix struct kernel_sigaction to match the kernel version [BZ #23069]
The RISC-V kernel doesn't define SA_RESTORER, hence the kernel version
of struct sigaction doesn't have the sa_restorer field. The default
kernel_sigaction.h therefore can't be used.

This patch adds a RISC-V specific version of kernel_sigaction.h to fix
the issue. This fixes for example the libnih testsuite.

Note that this patch is not needed in master as the bug has been fixed
by commit b4a5d26d88 ("linux: Consolidate sigaction implementation").
2018-04-28 13:17:00 +02:00
Florian Weimer 39071a5539 Linux i386: tst-bz21269 triggers SIGBUS on some kernels
In addition to SIGSEGV and SIGILL, SIGBUS is also a possible signal
generated by the kernel.

(cherry picked from commit 4d76d3e59d)
2018-03-29 13:01:57 +02:00
Andrew Senkevich 55ad82e45c Fix i386 memmove issue (bug 22644).
[BZ #22644]
	* sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed
	branch conditions.
	* string/test-memmove.c (do_test2): New testcase.

(cherry picked from commit cd66c0e584)
2018-03-28 22:19:41 +02:00
DJ Delorie df3ff4e49d Update ChangeLog for BZ 22884 - riscv fmax/fmin
(cherry picked from commit 7e04eb2932)
2018-03-19 19:39:25 +01:00
Andrew Waterman aab08776cc RISC-V: fmax/fmin: Handle signalling NaNs correctly.
RISC-V's fmax(sNAN,4) returns 4 but glibc expects it to return qNAN.

	* sysdeps/riscv/rvd/s_fmax.c (__fmax): Handle sNaNs correctly.
	* sysdeps/riscv/rvd/s_fmin.c (__fmin): Likewise.
	* sysdeps/riscv/rvf/s_fmaxf.c (__fmaxf): Likewise.
	* sysdeps/riscv/rvf/s_fminf.c (__fminf): Likewise.

(cherry picked from commit fdcc625376)
2018-03-19 19:38:28 +01:00
DJ Delorie 94145309f5 RISC-V: Do not initialize $gp in TLS macros.
RISC-V TLS doesn't require GP to be initialized, and doing so breaks
TLS in a shared object.

(cherry picked from commit 8090720a87)
2018-03-19 19:38:22 +01:00
Rafal Luzynski 3b92252641 NEWS: Add entries for bugs: 22848, 22932, 22937, 22963.
Alternative (nominative/genitive) month names have been added to the
Catalan and Czech locale data and the abbreviated alternative names to
Catalan and Greek.

(cherry picked from commit c553cd6f7e)
2018-03-16 23:57:20 +01:00
Rafal Luzynski 5d679b8bd7 cs_CZ locale: Add alternative month names (bug 22963).
Add alternative month names, primary month names are genitive now.

	[BZ #22963]
	* localedata/locales/cs_CZ (mon): Rename to...
	(alt_mon): This.
	(mon): Import from CLDR (genitive case).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 807fee29d2)
2018-03-16 23:57:20 +01:00
Rafal Luzynski 95c8ffa521 Greek (el_CY, el_GR) locales: Introduce ab_alt_mon (bug 22937).
As spotted by GNOME translation team, Greek language has the actually
visible difference between the abbreviated nominative and the abbreviated
genitive case for some month names.  Examples:

May:

abbreviated nominative: "Μάι" -> abbreviated genitive: "Μαΐ"

July:

abbreviated nominative: "Ιούν" -> abbreviated genitive: "Ιουλ"

and more month names with similar differences.

Original discussion: https://bugzilla.gnome.org/show_bug.cgi?id=793645#c21

	[BZ #22937]
	* localedata/locales/el_CY (abmon): Rename to...
	(ab_alt_mon): This.
	(abmon): Import from CLDR (abbreviated genitive case).
	* localedata/locales/el_GR (abmon): Rename to...
	(ab_alt_mon): This.
	(abmon): Import from CLDR (abbreviated genitive case).

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit e7155a28ef)
2018-03-16 23:57:20 +01:00
Rafal Luzynski 207e51524b lt_LT locale: Update abbreviated month names (bug 22932).
A GNOME translator asked to use the same abbreviated month names
as provided by CLDR.  This sounds reasonable.  See the discussion:
https://bugzilla.gnome.org/show_bug.cgi?id=793645#c27

	[BZ #22932]
	* localedata/locales/lt_LT (abmon): Synchronize with CLDR.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 71d7b12168)
2018-03-16 23:57:20 +01:00
Robert Buj 19be35a250 ca_ES locale: Update LC_TIME (bug 22848).
Add/fix alternative month names, long & short formats, am_pm,
abday settings, and improve indentation for Catalan.

	[BZ #22848]
	* localedata/locales/ca_ES (abmon): Rename to...
	(ab_alt_mon): This, then synchronize with CLDR (nominative case).
	(mon): Rename to...
	(alt_mon): This.
	(abmon): Import from CLDR (genitive case, month names preceded by
	"de" or "d’").
	(mon): Likewise.
	(abday): Synchronize with CLDR.
	(d_t_fmt): Likewise.
	(d_fmt): Likewise.
	(am_pm): Likewise.

	(LC_TIME): Improve indentation.
	(LC_TELEPHONE): Likewise.
	(LC_NAME): Likewise.
	(LC_ADDRESS): Likewise.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit a00bffe8b5)
2018-03-16 23:57:20 +01:00
Dmitry V. Levin b63daad97e Update translations from the Translation Project
* po/pt_BR.po: Update translations.

(cherry picked from commit 778f197486)
2018-03-12 19:26:40 +00:00
Adhemerval Zanella 1e52d8e65a i386: Fix i386 sigaction sa_restorer initialization (BZ#21269)
This patch fixes the i386 sa_restorer field initialization for sigaction
syscall for kernel with vDSO.  As described in bug report, i386 Linux
(and compat on x86_64) interprets SA_RESTORER clear with nonzero
sa_restorer as a request for stack switching if the SS segment is 'funny'.
This means that anything that tries to mix glibc's signal handling with
segmentation (for instance through modify_ldt syscall) is randomly broken
depending on what values lands in sa_restorer.

The testcase added  is based on Linux test tools/testing/selftests/x86/ldt_gdt.c,
more specifically in do_multicpu_tests function.  The main changes are:

  - C11 atomics instead of plain access.

  - Remove x86_64 support which simplifies the syscall handling and fallbacks.

  - Replicate only the test required to trigger the issue.

Checked on i686-linux-gnu.

	[BZ #21269]
	* sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269.
	* sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear
	sa_restorer for vDSO case.
	* sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file.

(cherry picked from commit 68448be208)
2018-03-12 19:26:40 +00:00
Andreas Schwab 78a90c2f74 Fix multiple definitions of __nss_*_database (bug 22918)
(cherry picked from commit eaf6753f8a)
2018-03-12 19:26:40 +00:00
DJ Delorie 7c6304182b [BZ #22342] Fix netgroup cache keys.
Unlike other nscd caches, the netgroup cache contains two types of
records - those for "iterate through a netgroup" (i.e. setnetgrent())
and those for "is this user in this netgroup" (i.e. innetgr()),
i.e. full and partial records.  The timeout code assumes these records
have the same key for the group name, so that the collection of records
that is "this netgroup" can be expired as a unit.

However, the keys are not the same, as the in-netgroup key is generated
by nscd rather than being passed to it from elsewhere, and is generated
without the trailing NUL.  All other keys have the trailing NUL, and as
noted in the linked BZ, debug statements confirm that two keys for the
same netgroup are added to the cache with two different lengths.

The result of this is that as records in the cache expire, the purge
code only cleans out one of the two types of entries, resulting in
stale, possibly incorrect, and possibly inconsistent cache data.

The patch simply includes the existing NUL in the computation for the
key length ('key' points to the char after the NUL, and 'group' to the
first char of the group, so 'key-group' includes the first char to the
NUL, inclusive).

	[BZ #22342]
	* nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in
	key value.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 1c81d55fc4)
2018-03-12 19:26:40 +00:00
Dmitry V. Levin 11dbb01577 linux/powerpc: sync sys/ptrace.h with Linux 4.15 [BZ #22433, #22807]
Tested with strace.

* sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h (__ptrace_request): Add
PTRACE_GETREGS, PTRACE_SETREGS, PTRACE_GETFPREGS, PTRACE_SETFPREGS,
PTRACE_GETVRREGS, PTRACE_SETVRREGS, PTRACE_GETEVRREGS,
PTRACE_SETEVRREGS, PTRACE_GETREGS64, PTRACE_SETREGS64,
PTRACE_GET_DEBUGREG, PTRACE_SET_DEBUGREG, PTRACE_GETVSRREGS,
PTRACE_SETVSRREGS, and PTRACE_SINGLEBLOCK.

(cherry picked from commit f5f473a9d0)
2018-03-12 19:26:40 +00:00
Tulio Magno Quites Machado Filho 8e79230a5e powerpc: Undefine Linux ptrace macros that conflict with __ptrace_request
Linux ptrace headers define macros whose tokens conflict with the
constants of enum __ptrace_request causing build errors when
asm/ptrace.h or linux/ptrace.h are included before sys/ptrace.h.

	* sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h: Undefine Linux
	macros used in __ptrace_request.

Signed-off-by: Tulio Magno Quites Machado Filho <tuliom@linux.vnet.ibm.com>
(cherry picked from commit 398c6fddaf)
2018-03-12 19:26:40 +00:00
Mike FABIAN f36553bf6a Add missing “reorder-end” in LC_COLLATE of et_EE [BZ #22517]
[BZ #22517]
	* localedata/locales/et_EE (LC_COLLATE): add missing “reorder-end”

(cherry picked from commit 7ec5f9465e)
2018-03-12 19:26:40 +00:00
Rical Jasan ea4ea9f875 Fix a typo in a comment.
* io/fcntl.h: Fix a typo in a comment.

(cherry picked from commit 0d217f4082)
2018-03-12 19:26:40 +00:00
Rical Jasan e12a365d3a manual: Update the _ISOC99_SOURCE description.
The current description refers to ISO C99 not being widely adopted,
which it is believed to be now.

	* manual/creature.texi (_ISOC99_SOURCE): Update the dated
	description.

(cherry picked from commit e8d190b9ed)
2018-03-12 19:26:40 +00:00
Rical Jasan b6c9b80e72 manual: Document missing feature test macros.
Several feature test macros are documented in features.h but absent in
the manual, and some documented macros accept undocumented values.
This commit updates the manual to mention all the accepted macros,
along with any values that hold special meaning.

	* manual/creature.texi (_POSIX_C_SOURCE): Document special
	values of 199606L, 200112L, and 200809L.
	(_XOPEN_SOURCE): Document special values of 600 and 700.
	(_ISOC11_SOURCE): Document macro.
	(_ATFILE_SOURCE): Likewise.
	(_FORTIFY_SOURCE): Likewise.

(cherry picked from commit 6a3962c4a4)
(cherry picked from commit da81ae645d)
2018-03-12 19:26:40 +00:00
Dmitry V. Levin fc0ad3d5e7 NEWS: add entries for bugs 22919 and 22926 2018-03-12 19:26:40 +00:00
Aurelien Jarno 3a53ef9b02 sparc32: Add nop before __startcontext to stop unwinding [BZ #22919]
On sparc32 tst-makecontext fails, as backtrace called within a context
created by makecontext to yield infinite backtrace.

Fix that the same way than nios2 by adding a nop just before
__startcontext. This is needed as otherwise FDE lookup just repeatedly
finds __setcontext's FDE in an infinite loop, due to the convention of
using 'address - 1' for FDE lookup.

Changelog:
	[BZ #22919]
	* sysdeps/unix/sysv/linux/sparc/sparc32/setcontext.S (__startcontext):
	Add nop before __startcontext, add explaining comments.

(cherry picked from commit 9aa5c222b9)
2018-03-09 00:30:56 +01:00
Adhemerval Zanella e51dfc04ef powerpc: Fix TLE build for SPE (BZ #22926)
Some SPE opcodes clashes with some recent PowerISA opcodes and
until recently gas did not complain about it.  However binutils
recently changed it and now VLE configured gas does not support to
assembler some instruction that might class with VLE (HTM for
instance).  It also does not help that glibc build hardware lock
elision support as default (regardless of assembler support).

Although runtime will not actually enables TLE on SPE hardware
(since kernel will not advertise it), I see little advantage on
adding HTM support on SPE built glibc.  SPE uses an incompatible
ABI which does not allow share the same build with default
powerpc and HTM code slows down SPE without any benefict.

This patch fixes it by only building HTM when SPE configuration
is not used.

Checked with a powerpc-linux-gnuspe build. I also did some sniff
tests on a e500 hardware without any issue.

	[BZ #22926]
	* sysdeps/powerpc/powerpc32/sysdep.h (ABORT_TRANSACTION_IMPL): Define
	empty for __SPE__.
	* sysdeps/powerpc/sysdep.h (ABORT_TRANSACTION): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/elision-lock.c (__lll_lock_elision):
	Do not build hardware transactional code for __SPE__.
	* sysdeps/unix/sysv/linux/powerpc/elision-trylock.c
	(__lll_trylock_elision): Likewise.
	* sysdeps/unix/sysv/linux/powerpc/elision-unlock.c
	(__lll_unlock_elision): Likewise.

Cherry-pick from e921c89e01.
2018-03-08 09:02:06 -03:00
Rical Jasan b4108a361f manual: Improve documentation of get_current_dir_name. [BZ #6889]
This is a minor rewording to clarify the behaviour of
get_current_dir_name.  Additionally, the @vindex is moved above the
@deftypefun so that following links give a better result with regard
to context.

	[BZ #6889]
	* manual/filesys.texi (get_current_dir_name): Clarify
	behaviour.

(cherry picked from commit 7d15ef84f5)
2018-02-19 20:39:17 +00:00
Rical Jasan aa02f2b2f5 manual: Fix a syntax error.
The opening parenthesis for function arguments in an @deftypefun need
to be separated from the function name.  This isn't just a matter of
the GNU coding style---it causes the "(void" (in this case) to be
rendered as a part of the function name, causing a visual defect, and
also results in a warning to the following effect during `make pdf':

  Warning: unbalanced parentheses in @def...)

	* manual/platform.texi (__riscv_flush_icache): Fix @deftypefun
	syntax.

(cherry picked from commit 16efad5171)
2018-02-19 20:39:17 +00:00
Rical Jasan 6031b49c39 manual: Fix Texinfo warnings about improper node names.
A number of cross-references to the GCC info manual cause Texinfo
warnings; e.g.:

  ./creature.texi:11: warning: @xref node name should not contain `.'

This is due to "gcc.info" being used in the INFO-FILE-NAME (fourth)
argument.  Changing it to "gcc" removes these warnings.  (Manually
confirmed equivalent behaviour for make info, html, and pdf.)

	* manual/creature.texi: Convert references to gcc.info to gcc.
	* manual/stdio.texi: Likewise.
	* manual/string.texi: Likewise.

(cherry picked from commit 1f6676d7da)
2018-02-19 20:39:17 +00:00
Aurelien Jarno d5f136743d Fix posix/tst-glob_lstat_compat on alpha [BZ #22818]
The tst-glob_lstat_compat test needs to run tests on the previous
version of glob. On alpha, there are three versions of glob, GLIBC_2.0,
GLIBC_2.1 and GLIBC_2.27, while on other architectures there are only
the GLIBC_2.0 and GLIBC_2.27 version. Therefore on alpha the previous
version is GLIBC_2.1 and not GLIBC_2.0.

Changelog:
	[BZ #22818]
	* posix/tst-glob_lstat_compat.c [__alpha__] (glob): Access
	the GLIBC_2.1 version.

(cherry picked from commit f8d7958289)
2018-02-19 20:39:17 +00:00
Sean McKean 1b7671f6e1 time: Reference CLOCKS_PER_SEC in clock comment [BZ #22735]
(cherry picked from commit 09e56b9e18)
2018-02-19 20:39:17 +00:00
Dmitry V. Levin 516fa60804 linux/aarch64: sync sys/ptrace.h with Linux 4.15 [BZ #22433]
Remove compat-specific constants that were never exported by kernel
headers under these names.  Before linux commit v3.7-rc1~16^2~1 they
were exported with COMPAT_ prefix, and since that commit they are not
exported at all.

* sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h (__ptrace_request):
Remove arm-specific PTRACE_GET_THREAD_AREA, PTRACE_GETHBPREGS,
and PTRACE_SETHBPREGS.

(cherry picked from commit 2fd4bbaa14)
2018-02-19 20:39:17 +00:00
Dmitry V. Levin 79543e5479 NEWS: add an entry for bug 22827 2018-02-19 20:39:17 +00:00
Adhemerval Zanella 55171cd08f Update SH libm-tests-ulps
* sysdeps/sh/libm-test-ulps: Update.

Signed-off-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
2018-02-14 14:04:44 -02:00
DJ Delorie 750a1c253f [RISC-V] Fix parsing flags in ELF64 files.
When ldconfig reads Elf64 files to determine the ABI, it used the
Elf32 type, so read the wrong location, and stored the wrong ABI
type in the cache, making the cache useless.  This patch uses
an Elf64 type for Elf64 objects instead.

Note that pre-patch caches might need to be manually removed and
regenerated to get the correct ABIs stored.

	[BZ #22827]
	* sysdeps/unix/sysv/linux/riscv/readelflib.c (process_elf_file): Use
	64-bit ELF type for 64-bit ELF objects.

(cherry picked from commit 6a1ff640dc)
2018-02-09 19:24:48 -05:00
Igor Gnatenko 56170e064e Linux: use reserved name __key in pkey_get [BZ #22797]
_key is not reserved name and we should avoid using that. It seems that
it was simple typo when pkey_* was implemented.

(cherry picked from commit 388ff7bd0d)
2018-02-07 13:53:10 +01:00
H.J. Lu 00c5a2d77a Add a missing ChangeLog item in commit 371b220f62
(cherry picked from commit 658050164d)
2018-02-06 03:07:55 -08:00
Dmitry V. Levin c8ad6ac1d1 NEWS: add an entry for bug 22638 2018-02-06 09:31:30 +00:00
H.J. Lu ce8a6550fa sparc: Check PIC instead of SHARED in start.S [BZ #22638]
Since start.o may be compiled as PIC, we should check PIC instead of
SHARED.

	[BZ #22638]
	* sysdeps/sparc/sparc32/start.S (_start): Check PIC instead of
	SHARED.
	* sysdeps/sparc/sparc64/start.S (_start): Likewise.

(cherry picked from commit 371b220f62)
2018-02-06 09:31:30 +00:00
Florian Weimer bdac1623cc Record CVE-2018-6551 in NEWS and ChangeLog [BZ #22774]
(cherry picked from commit 71aa429b02)
2018-02-06 09:21:00 +01:00
327 changed files with 17910 additions and 6993 deletions
+1152
View File
File diff suppressed because it is too large Load Diff
-9
View File
@@ -441,15 +441,6 @@ Permission to use, copy, modify, and distribute this
software is freely granted, provided that this notice
is preserved.
Part of stdio-common/tst-printf.c is copyright C E Chew:
(C) Copyright C E Chew
Feel free to copy, use and distribute this software provided:
1. you do not pretend that you wrote it
2. you leave this copyright notice intact.
Various long double libm functions are copyright Stephen L. Moshier:
Copyright 2001 by Stephen L. Moshier <moshier@na-net.ornl.gov>
+208
View File
@@ -4,6 +4,209 @@ See the end for copying conditions.
Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
using `glibc' in the "product" field.
Version 2.27.1
Major new features:
* The entry for the new Japanese era has been added for ja_JP locale.
* Nominative and genitive month names are now supported for the Catalan and
Czech languages. The Catalan and Greek languages now support abbreviated
alternative month names.
* Parsing of dynamic string tokens in DT_RPATH, DT_RUNPATH, DT_NEEDED,
DT_AUXILIARY, and DT_FILTER has been expanded to support the full
range of ELF gABI expressions including such constructs as
'$ORIGIN$ORIGIN' (if valid). For SUID/GUID applications the rules
have been further restricted, and where in the past a dynamic string
token sequence may have been interpreted as a literal string it will
now cause a load failure. These load failures were always considered
unspecified behaviour from the perspective of the dynamic loader, and
for safety are now load errors e.g. /foo/${ORIGIN}.so in DT_NEEDED
results in a load failure now.
Deprecated and removed features, and other changes affecting compatibility:
* The copy_file_range function fails with ENOSYS if the kernel does not
support the system call of the same name. Previously, user space
emulation was performed, but its behavior did not match the kernel
behavior, which was deemed too confusing. Applications which use the
copy_file_range function will have to be run on kernels which implement
the copy_file_range system call. Support for most architectures was added
in version 4.5 of the mainline Linux kernel.
Security related changes:
CVE-2016-10228: An infinite loop has been fixed in the iconv program when
invoked with the -c option and when processing invalid multi-byte input
sequences. Reported by Jan Engelhardt.
CVE-2017-18269: An SSE2-based memmove implementation for the i386
architecture could corrupt memory. Reported by Max Horn.
CVE-2018-11236: Very long pathname arguments to realpath function could
result in an integer overflow and buffer overflow. Reported by Alexey
Izbyshev.
CVE-2018-11237: The mempcpy implementation for the Intel Xeon Phi
architecture could write beyond the target buffer, resulting in a buffer
overflow. Reported by Andreas Schwab.
CVE-2018-19591: A file descriptor leak in if_nametoindex can lead to a
denial of service due to resource exhaustion when processing getaddrinfo
calls with crafted host names. Reported by Guido Vranken.
CVE-2019-6488: On x32, the size_t parameter may be passed in the lower
32 bits of a 64-bit register with with non-zero upper 32 bit. When it
happened, accessing the 32-bit size_t value as the full 64-bit register
in the assembly string/memory functions would cause a buffer overflow.
Reported by H.J. Lu.
CVE-2019-7309: x86-64 memcmp used signed Jcc instructions to check
size. For x86-64, memcmp on an object size larger than SSIZE_MAX
has undefined behavior. On x32, the size_t argument may be passed
in the lower 32 bits of the 64-bit RDX register with non-zero upper
32 bits. When it happened with the sign bit of RDX register set,
memcmp gave the wrong result since it treated the size argument as
zero. Reported by H.J. Lu.
CVE-2019-19126: ld.so failed to ignore the LD_PREFER_MAP_32BIT_EXEC
environment variable during program execution after a security
transition, allowing local attackers to restrict the possible mapping
addresses for loaded libraries and thus bypass ASLR for a setuid
program. Reported by Marcin Kościelnicki.
CVE-2020-1751: A defect in the PowerPC backtrace function could cause an
out-of-bounds write when executed in a signal frame context.
CVE-2020-1752: A use-after-free vulnerability in the glob function when
expanding ~user has been fixed.
CVE-2020-6096: A signed comparison vulnerability in the ARMv7 memcpy and
memmove functions has been fixed. Discovered by Jason Royes and Samual
Dytrych of the Cisco Security Assessment and Penetration Team (See
TALOS-2020-1019).
CVE-2020-10029: Trigonometric functions on x86 targets suffered from stack
corruption when they were passed a pseudo-zero argument. Reported by Guido
Vranken / ForAllSecure Mayhem.
CVE-2020-27618: An infinite loop has been fixed in the iconv program when
invoked with input containing redundant shift sequences in the IBM1364,
IBM1371, IBM1388, IBM1390, or IBM1399 character sets.
CVE-2020-29562: An assertion failure has been fixed in the iconv function
when invoked with UCS4 input containing an invalid character.
CVE-2021-27645: The nameserver caching daemon (nscd), when processing
a request for netgroup lookup, may crash due to a double-free,
potentially resulting in degraded service or Denial of Service on the
local system. Reported by Chris Schanzle.
CVE-2021-35942: The wordexp function may overflow the positional
parameter number when processing the expansion resulting in a crash.
Reported by Philippe Antoine.
The following bugs are resolved with this release:
[6889] 'PWD' mentioned but not specified
[16335] Feature test macro documentation incomplete and out of date
[17343] Signed integer overflow in /stdlib/random_r.c
[18018] Additional $ORIGIN handling issues (CVE-2011-0536)
[18035] Fix pldd hang
[18830] locale: iconv -c -f ascii with >buffer size worth of input before
invalid input drops valid char
[19519] iconv(1) with -c option hangs on illegal multi-byte sequences
(CVE-2016-10228)
[20419] files with large allocated notes crash in open_verify
[20568] Fix crash in _IO_wfile_sync
[21269] i386 sigaction sa_restorer handling is wrong
[21812] getifaddrs: Don't return ifa entries with NULL names
[21942] _dl_dst_substitute incorrectly handles $ORIGIN: with AT_SECURE=1
[22342] NSCD not properly caching netgroup
[22638] sparc: static binaries are broken if glibc is built by gcc
configured with --enable-default-pie
[22644] memmove-sse2-unaligned on 32bit x86 produces garbage when crossing
2GB threshold
[22735] Misleading typo in time.h source comment regarding CLOCKS_PER_SECOND
[22753] libc: preadv2/pwritev2 fallback code should handle offset=-1
[22786] Stack buffer overflow in realpath() if input size is close
to SSIZE_MAX
[22797] Linux: use reserved name __key in pkey_get
[22807] PTRACE_* constants missing for powerpc
[22818] posix/tst-glob_lstat_compat failure on alpha
[22827] RISC-V ELF64 parser mis-reads flag in ldconfig
[22848] ca_ES: update date definitions from CLDR
[22884] RISCV fmax/fmin handle signalling NANs incorrectly
[22918] multiple common of `__nss_shadow_database'
[22919] sparc32: backtrace yields infinite backtrace with makecontext
[22926] FTBFS on powerpcspe
[22927] libanl: properly cleanup if first helper thread creation failed
[22932] lt_LT: Update of abbreviated month names from CLDR required
[22937] Greek (el_GR, el_CY) locales actually need ab_alt_mon
[22947] FAIL: misc/tst-preadvwritev2
[22963] cs_CZ: Add alternative month names
[22964] The Japanese Era name will be changed on May 1, 2019
[22996] localedata: change LC_PAPER to en_US in es_BO locale
[23005] Crash in __res_context_send after memory allocation failure
[23036] regexec: Fix off-by-one bug in weight comparison
[23037] initialize msg_flags to zero for sendmmsg() calls
[23069] sigaction broken on riscv64-linux-gnu
[23102] Incorrect parsing of consecutive $ variables in runpath entries
[23132] localedata: Missing transliterations in Miscellaneous Mathematical
Symbols-A/B Unicode blocks
[23137] s390: pthread_join sometimes block indefinitely (on 31bit and libc
build with -Os)
[23152] gd_GB: Fix typo in "May" (abbreviated)
[23166] sunrpc: Remove stray exports without --enable-obsolete-rpc
[23171] Fix parameter type in C++ version of iseqsig
[23196] __mempcpy_avx512_no_vzeroupper mishandles large copies
[23236] Harden function pointers in _IO_str_fields
[23253] Set 387 and SSE2 rounding mode for tgamma on i386
[23259] Unsubstituted ${ORIGIN} remains in DT_NEEDED for AT_SECURE
[23264] libc: posix_spawnp wrongly executes ENOEXEC in non compat mode
[23275] Race in pthread_mutex_lock while promoting to PTHREAD_MUTEX_ELISION_NP
[23313] libio: Disable vtable validation in case of interposition
[23349] Various glibc headers no longer compatible with <linux/time.h>
[23363] stdio-common/tst-printf.c has non-free license
[23456] Wrong index_cpu_LZCNT
[23459] COMMON_CPUID_INDEX_80000001 isn't populated for Intel processors
[23520] nscd: nscd: Use-after-free in addgetnetgrentX and its callers
[23538] pthread_cond_broadcast: Fix waiters-after-spinning case
[23562] signal: Use correct type for si_band in siginfo_t
[23579] libc: Errors misreported in preadv2
[23614] powerpc: missing CFI register information in __mpn_* functions
[23690] Fix _dl_profile_fixup data-dependency issue
[23709] Fix CPU string flags for Haswell-type CPUs
[23821] si_band in siginfo_t has wrong type long int on sparc64
[23822] ia64 static libm.a is missing exp2f, log2f and powf symbols
[23861] rdlock stalls indefinitely on an unlocked pthread rwlock
[23907] Incorrect double-free malloc tcache check disregards tcache size
[23927] Linux if_nametoindex() does not close descriptor (CVE-2018-19591)
[24018] gettext may return NULL
[24027] malloc: Integer overflow in realloc
[24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488)
[24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309)
[24180] pthread_mutex_trylock does not use the correct order of instructions
while maintaining the robust mutex list due to missing compiler barriers
[24228] old x86 applications that use legacy libio crash on exit
[24531] Malloc tunables give tcache assertion failures
[24744] io: Remove the copy_file_range emulation
[25203] libio: Disable vtable validation for pre-2.1 interposed handles
[25204] Ignore LD_PREFER_MAP_32BIT_EXEC for SUID programs
[25232] No const correctness for strchr et al. for Clang++
[25414] 'glob' use-after-free bug (CVE-2020-1752)
[25423] Array overflow in backtrace on powerpc
[25487] sinl() stack corruption from crafted input (CVE-2020-10029)
[25620] libc: Signed comparison vulnerability in the ARMv7 memcpy() (CVE-2020-6096)
[26224] iconv hangs when converting some invalid inputs from several IBM
character sets (CVE-2020-27618)
[26383] bind_textdomain_codeset doesn't accept //TRANSLIT anymore
[26923] Assertion failure in iconv when converting invalid UCS4 (CVE-2020-29562)
[27462] nscd: double-free in nscd (CVE-2021-27645)
[28011] libc: Wild read in wordexp (parse_param) (CVE-2021-35942)
Version 2.27
@@ -262,6 +465,10 @@ Security related changes:
an object size near the value of SIZE_MAX, would return a pointer to a
buffer which is too small, instead of NULL. Reported by Jakub Wilk.
CVE-2018-6551: The malloc function, when called with an object size near
the value of SIZE_MAX, would return a pointer to a buffer which is too
small, instead of NULL.
The following bugs are resolved with this release:
[866] glob: glob should match dangling symlinks
@@ -334,6 +541,7 @@ The following bugs are resolved with this release:
[21326] libc: C99 functions are not declared for C++11 and later if
_GNU_SOURCE is not predefined by g++
[21457] libc: sys/ucontext.h namespace
[21508] locale: intl/tst-gettext failure with latest msgfmt
[21530] libc: tmpfile() should be implemented using O_TMPFILE
[21660] math: GCC fails to compile a formula with tgmath.h
[21672] nptl: sys-libs/glibc on ia64 crashes on thread exit: signal
+1
View File
@@ -24,6 +24,7 @@
#define STRCASESTR simple_strcasestr
#define NO_ALIAS
#define __strncasecmp strncasecmp
#define __strnlen strnlen
#include "../string/strcasestr.c"
+3
View File
@@ -22,6 +22,9 @@
#define STRSTR simple_strstr
#undef libc_hidden_builtin_def
#define libc_hidden_builtin_def(X)
#define __strnlen strnlen
#include "../string/strstr.c"
+1
View File
@@ -28,5 +28,6 @@
#define RWF_DSYNC 0x00000002 /* per-IO O_DSYNC. */
#define RWF_SYNC 0x00000004 /* per-IO O_SYNC. */
#define RWF_NOWAIT 0x00000008 /* per-IO nonblocking mode. */
#define RWF_APPEND 0x00000010 /* per-IO O_APPEND. */
#endif /* sys/uio_ext.h */
+5
View File
@@ -58,6 +58,11 @@ $1 ~ "msg(id|str)" {
next
}
/^"POT-Creation-Date: [0-9-]+ [0-9:+-]+\\n"/ {
# Ignore POT-Creation-Date to match what is done in intl/Makefile.
next
}
/^".*"/ {
# Append to current message
sub(/^"/, "", $0)
+13 -13
View File
@@ -367,7 +367,7 @@ while ($#headers >= 0) {
s/^optional-//;
$optional = 1;
}
if (/^element *({([^}]*)}|([^{ ]*)) *({([^}]*)}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
if (/^element *(\{([^}]*)\}|([^{ ]*)) *(\{([^}]*)\}|([^{ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
my($struct) = "$2$3";
my($type) = "$5$6";
my($member) = "$7";
@@ -556,7 +556,7 @@ while ($#headers >= 0) {
"Symbol \"$symbol\" has not the right value.", $res,
$xfail);
}
} elsif (/^type *({([^}]*)|([a-zA-Z0-9_]*))/) {
} elsif (/^type *(\{([^}]*)|([a-zA-Z0-9_]*))/) {
my($type) = "$2$3";
my($maybe_opaque) = 0;
@@ -586,7 +586,7 @@ while ($#headers >= 0) {
? "NOT AVAILABLE"
: "Type \"$type\" not available."), $missing, $optional,
$xfail);
} elsif (/^tag *({([^}]*)|([a-zA-Z0-9_]*))/) {
} elsif (/^tag *(\{([^}]*)|([a-zA-Z0-9_]*))/) {
my($type) = "$2$3";
# Remember that this name is allowed.
@@ -607,7 +607,7 @@ while ($#headers >= 0) {
compiletest ($fnamebase, "Testing for type $type",
"Type \"$type\" not available.", $missing, 0, $xfail);
} elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
my($rettype) = "$2$3";
my($fname) = "$4";
my($args) = "$5";
@@ -644,7 +644,7 @@ while ($#headers >= 0) {
"Function \"$fname\" has incorrect type.", $res, 0,
$xfail);
}
} elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
my($rettype) = "$2$3";
my($fname) = "$4";
my($args) = "$5";
@@ -681,7 +681,7 @@ while ($#headers >= 0) {
"Function \"$fname\" has incorrect type.", $res, 0,
$xfail);
}
} elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) *(.*)/) {
} elsif (/^variable *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) *(.*)/) {
my($type) = "$2$3";
my($vname) = "$4";
my($rest) = "$5";
@@ -713,7 +713,7 @@ while ($#headers >= 0) {
compiletest ($fnamebase, "Test for type of variable $fname",
"Variable \"$vname\" has incorrect type.", $res, 0, $xfail);
} elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^macro-function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
my($rettype) = "$2$3";
my($fname) = "$4";
my($args) = "$5";
@@ -812,11 +812,11 @@ while ($#headers >= 0) {
s/^xfail(\[([^\]]*)\])?-//;
s/^optional-//;
if (/^element *({([^}]*)}|([^ ]*)) *({([^}]*)}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
if (/^element *(\{([^}]*)\}|([^ ]*)) *(\{([^}]*)\}|([^ ]*)) *([A-Za-z0-9_]*) *(.*)/) {
push @allow, $7;
} elsif (/^(macro|constant|macro-constant|macro-int-constant) +([a-zA-Z0-9_]*) *(?:{([^}]*)} *)?(?:([>=<!]+) ([A-Za-z0-9_-]*))?/) {
push @allow, $2;
} elsif (/^(type|tag) *({([^}]*)|([a-zA-Z0-9_]*))/) {
} elsif (/^(type|tag) *(\{([^}]*)|([a-zA-Z0-9_]*))/) {
my($type) = "$3$4";
# Remember that this name is allowed.
@@ -827,13 +827,13 @@ while ($#headers >= 0) {
} else {
push @allow, $type;
}
} elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) [(][*]([a-zA-Z0-9_]*) ([(].*[)])/) {
push @allow, $4;
} elsif (/^function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
push @allow, $4;
} elsif (/^variable *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
} elsif (/^variable *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*)/) {
push @allow, $4;
} elsif (/^macro-function *({([^}]*)}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
} elsif (/^macro-function *(\{([^}]*)\}|([a-zA-Z0-9_]*)) ([a-zA-Z0-9_]*) ([(].*[)])/) {
push @allow, $4;
} elsif (/^symbol *([a-zA-Z0-9_]*) *([A-Za-z0-9_-]*)?/) {
push @allow, $1;
+2 -1
View File
@@ -170,7 +170,8 @@ element siginfo_t pid_t si_pid
element siginfo_t uid_t si_uid
element siginfo_t {void*} si_addr
element siginfo_t int si_status
element siginfo_t long si_band
// Bug 23821: si_band has type int on sparc64.
xfail[sparc64-linux]-element siginfo_t long si_band
# endif
# ifndef XPG42
element siginfo_t {union sigval} si_value
+2 -1
View File
@@ -44,7 +44,8 @@ element siginfo_t pid_t si_pid
element siginfo_t uid_t si_uid
element siginfo_t {void*} si_addr
element siginfo_t int si_status
element siginfo_t long si_band
// Bug 23821: si_band has type int on sparc64.
xfail[sparc64-linux]-element siginfo_t long si_band
# ifndef XPG42
element siginfo_t {union sigval} si_value
# endif
+12
View File
@@ -88,6 +88,18 @@ handle_signal (int signum)
}
/* Symbol names are not available for static functions, so we do not
check do_test. */
/* Check that backtrace does not return more than what fits in the array
(bug 25423). */
for (int j = 0; j < NUM_FUNCTIONS; j++)
{
n = backtrace (addresses, j);
if (n > j)
{
FAIL ();
return;
}
}
}
NO_INLINE int
+2 -2
View File
@@ -55,8 +55,8 @@ __vasprintf_chk (char **result_ptr, int flags, const char *format,
_IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
_IO_str_init_static_internal (&sf, string, init_string_size, string);
sf._sbf._f._flags &= ~_IO_USER_BUF;
sf._s._allocate_buffer = (_IO_alloc_type) malloc;
sf._s._free_buffer = (_IO_free_type) free;
sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
sf._s._free_buffer_unused = (_IO_free_type) free;
/* For flags > 0 (i.e. __USE_FORTIFY_LEVEL > 1) request that %n
can only come from read-only format strings. */
+4 -1
View File
@@ -197,7 +197,10 @@ check_free (struct dl_action_result *rec)
Dl_info info;
if (_dl_addr (check_free, &info, &map, NULL) != 0 && map->l_ns == 0)
#endif
free ((char *) rec->errstring);
{
free ((char *) rec->errstring);
rec->errstring = NULL;
}
}
}
+6 -2
View File
@@ -187,7 +187,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
tst-debug1 tst-main1
tst-debug1 tst-main1 tst-big-note
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -272,7 +272,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
tst-main1mod tst-libc_dlvsym-dso
tst-main1mod tst-libc_dlvsym-dso \
tst-big-note-lib
ifeq (yes,$(have-mtls-dialect-gnu2))
tests += tst-gnu2-tls1
modules-names += tst-gnu2-tls1mod
@@ -1446,3 +1448,5 @@ $(objpfx)tst-libc_dlvsym-static: $(common-objpfx)dlfcn/libdl.a
tst-libc_dlvsym-static-ENV = \
LD_LIBRARY_PATH=$(objpfx):$(common-objpfx):$(common-objpfx)dlfcn
$(objpfx)tst-libc_dlvsym-static.out: $(objpfx)tst-libc_dlvsym-dso.so
$(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so
+1 -1
View File
@@ -100,7 +100,7 @@ struct list
({ \
const char *__str = (str); \
const char *__result = __str; \
size_t __dst_cnt = DL_DST_COUNT (__str); \
size_t __dst_cnt = _dl_dst_count (__str); \
\
if (__dst_cnt != 0) \
{ \
-13
View File
@@ -18,19 +18,6 @@
#include "trusted-dirs.h"
/* Determine the number of DST elements in the name. Only if IS_PATH is
nonzero paths are recognized (i.e., multiple, ':' separated filenames). */
#define DL_DST_COUNT(name) \
({ \
size_t __cnt = 0; \
const char *__sf = strchr (name, '$'); \
\
if (__glibc_unlikely (__sf != NULL)) \
__cnt = _dl_dst_count (__sf); \
\
__cnt; })
#ifdef SHARED
# define IS_RTLD(l) (l) == &GL(dl_rtld_map)
#else
+153 -81
View File
@@ -122,12 +122,6 @@ is_trusted_path_normalize (const char *path, size_t len)
if (len == 0)
return false;
if (*path == ':')
{
++path;
--len;
}
char *npath = (char *) alloca (len + 2);
char *wnp = npath;
while (*path != '\0')
@@ -178,114 +172,165 @@ is_trusted_path_normalize (const char *path, size_t len)
return false;
}
/* Given a substring starting at INPUT, just after the DST '$' start
token, determine if INPUT contains DST token REF, following the
ELF gABI rules for DSTs:
* Longest possible sequence using the rules (greedy).
* Must start with a $ (enforced by caller).
* Must follow $ with one underscore or ASCII [A-Za-z] (caller
follows these rules for REF) or '{' (start curly quoted name).
* Must follow first two characters with zero or more [A-Za-z0-9_]
(enforced by caller) or '}' (end curly quoted name).
If the sequence is a DST matching REF then the length of the DST
(excluding the $ sign but including curly braces, if any) is
returned, otherwise 0. */
static size_t
is_dst (const char *start, const char *name, const char *str, int secure)
is_dst (const char *input, const char *ref)
{
size_t len;
bool is_curly = false;
if (name[0] == '{')
/* Is a ${...} input sequence? */
if (input[0] == '{')
{
is_curly = true;
++name;
++input;
}
len = 0;
while (name[len] == str[len] && name[len] != '\0')
++len;
/* Check for matching name, following closing curly brace (if
required), or trailing characters which are part of an
identifier. */
size_t rlen = strlen (ref);
if (strncmp (input, ref, rlen) != 0
|| (is_curly && input[rlen] != '}')
|| ((input[rlen] >= 'A' && input[rlen] <= 'Z')
|| (input[rlen] >= 'a' && input[rlen] <= 'z')
|| (input[rlen] >= '0' && input[rlen] <= '9')
|| (input[rlen] == '_')))
return 0;
if (is_curly)
{
if (name[len] != '}')
return 0;
/* Point again at the beginning of the name. */
--name;
/* Skip over closing curly brace and adjust for the --name. */
len += 2;
}
else if (name[len] != '\0' && name[len] != '/')
return 0;
if (__glibc_unlikely (secure)
&& ((name[len] != '\0' && name[len] != '/')
|| (name != start + 1)))
return 0;
return len;
/* Count the two curly braces. */
return rlen + 2;
else
return rlen;
}
/* INPUT is the start of a DST sequence at the first '$' occurrence.
If there is a DST we call into _dl_dst_count to count the number of
DSTs. We count all known DSTs regardless of __libc_enable_secure;
the caller is responsible for enforcing the security of the
substitution rules (usually _dl_dst_substitute). */
size_t
_dl_dst_count (const char *name)
_dl_dst_count (const char *input)
{
const char *const start = name;
size_t cnt = 0;
input = strchr (input, '$');
/* Most likely there is no DST. */
if (__glibc_likely (input == NULL))
return 0;
do
{
size_t len;
/* $ORIGIN is not expanded for SUID/GUID programs (except if it
is $ORIGIN alone) and it must always appear first in path. */
++name;
if ((len = is_dst (start, name, "ORIGIN", __libc_enable_secure)) != 0
|| (len = is_dst (start, name, "PLATFORM", 0)) != 0
|| (len = is_dst (start, name, "LIB", 0)) != 0)
++input;
/* All DSTs must follow ELF gABI rules, see is_dst (). */
if ((len = is_dst (input, "ORIGIN")) != 0
|| (len = is_dst (input, "PLATFORM")) != 0
|| (len = is_dst (input, "LIB")) != 0)
++cnt;
name = strchr (name + len, '$');
/* There may be more than one DST in the input. */
input = strchr (input + len, '$');
}
while (name != NULL);
while (input != NULL);
return cnt;
}
/* Process INPUT for DSTs and store in RESULT using the information
from link map L to resolve the DSTs. This function only handles one
path at a time and does not handle colon-separated path lists (see
fillin_rpath ()). Lastly the size of result in bytes should be at
least equal to the value returned by DL_DST_REQUIRED. Note that it
is possible for a DT_NEEDED, DT_AUXILIARY, and DT_FILTER entries to
have colons, but we treat those as literal colons here, not as path
list delimeters. */
char *
_dl_dst_substitute (struct link_map *l, const char *name, char *result)
_dl_dst_substitute (struct link_map *l, const char *input, char *result)
{
const char *const start = name;
/* Now fill the result path. While copying over the string we keep
track of the start of the last path element. When we come across
a DST we copy over the value or (if the value is not available)
leave the entire path element out. */
/* Copy character-by-character from input into the working pointer
looking for any DSTs. We track the start of input and if we are
going to check for trusted paths, all of which are part of $ORIGIN
handling in SUID/SGID cases (see below). In some cases, like when
a DST cannot be replaced, we may set result to an empty string and
return. */
char *wp = result;
char *last_elem = result;
const char *start = input;
bool check_for_trusted = false;
do
{
if (__glibc_unlikely (*name == '$'))
if (__glibc_unlikely (*input == '$'))
{
const char *repl = NULL;
size_t len;
++name;
if ((len = is_dst (start, name, "ORIGIN", __libc_enable_secure)) != 0)
++input;
if ((len = is_dst (input, "ORIGIN")) != 0)
{
repl = l->l_origin;
/* For SUID/GUID programs we normally ignore the path with
$ORIGIN in DT_RUNPATH, or DT_RPATH. However, there is
one exception to this rule, and it is:
* $ORIGIN appears as the first path element, and is
the only string in the path or is immediately
followed by a path separator and the rest of the
path.
* The path is rooted in a trusted directory.
This exception allows such programs to reference
shared libraries in subdirectories of trusted
directories. The use case is one of general
organization and deployment flexibility.
Trusted directories are usually such paths as "/lib64"
or "/usr/lib64", and the usual RPATHs take the form of
[$ORIGIN/../$LIB/somedir]. */
if (__glibc_unlikely (__libc_enable_secure)
&& !(input == start + 1
&& (input[len] == '\0' || input[len] == '/')))
repl = (const char *) -1;
else
repl = l->l_origin;
check_for_trusted = (__libc_enable_secure
&& l->l_type == lt_executable);
}
else if ((len = is_dst (start, name, "PLATFORM", 0)) != 0)
else if ((len = is_dst (input, "PLATFORM")) != 0)
repl = GLRO(dl_platform);
else if ((len = is_dst (start, name, "LIB", 0)) != 0)
else if ((len = is_dst (input, "LIB")) != 0)
repl = DL_DST_LIB;
if (repl != NULL && repl != (const char *) -1)
{
wp = __stpcpy (wp, repl);
name += len;
input += len;
}
else if (len > 1)
else if (len != 0)
{
/* We cannot use this path element, the value of the
replacement is unknown. */
wp = last_elem;
break;
/* We found a valid DST that we know about, but we could
not find a replacement value for it, therefore we
cannot use this path and discard it. */
*result = '\0';
return result;
}
else
/* No DST we recognize. */
@@ -293,16 +338,26 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result)
}
else
{
*wp++ = *name++;
*wp++ = *input++;
}
}
while (*name != '\0');
while (*input != '\0');
/* In SUID/SGID programs, after $ORIGIN expansion the normalized
path must be rooted in one of the trusted directories. */
path must be rooted in one of the trusted directories. The $LIB
and $PLATFORM DST cannot in any way be manipulated by the caller
because they are fixed values that are set by the dynamic loader
and therefore any paths using just $LIB or $PLATFORM need not be
checked for trust, the authors of the binaries themselves are
trusted to have designed this correctly. Only $ORIGIN is tested in
this way because it may be manipulated in some ways with hard
links. */
if (__glibc_unlikely (check_for_trusted)
&& !is_trusted_path_normalize (last_elem, wp - last_elem))
wp = last_elem;
&& !is_trusted_path_normalize (result, wp - result))
{
*result = '\0';
return result;
}
*wp = '\0';
@@ -310,13 +365,13 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result)
}
/* Return copy of argument with all recognized dynamic string tokens
($ORIGIN and $PLATFORM for now) replaced. On some platforms it
might not be possible to determine the path from which the object
belonging to the map is loaded. In this case the path element
containing $ORIGIN is left out. */
/* Return a malloc allocated copy of INPUT with all recognized DSTs
replaced. On some platforms it might not be possible to determine the
path from which the object belonging to the map is loaded. In this
case the path containing the DST is left out. On error NULL
is returned. */
static char *
expand_dynamic_string_token (struct link_map *l, const char *s)
expand_dynamic_string_token (struct link_map *l, const char *input)
{
/* We make two runs over the string. First we determine how large the
resulting string is and then we copy it over. Since this is no
@@ -326,22 +381,22 @@ expand_dynamic_string_token (struct link_map *l, const char *s)
size_t total;
char *result;
/* Determine the number of DST elements. */
cnt = DL_DST_COUNT (s);
/* Determine the number of DSTs. */
cnt = _dl_dst_count (input);
/* If we do not have to replace anything simply copy the string. */
if (__glibc_likely (cnt == 0))
return __strdup (s);
return __strdup (input);
/* Determine the length of the substituted string. */
total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
total = DL_DST_REQUIRED (l, input, strlen (input), cnt);
/* Allocate the necessary memory. */
result = (char *) malloc (total + 1);
if (result == NULL)
return NULL;
return _dl_dst_substitute (l, s, result);
return _dl_dst_substitute (l, input, result);
}
@@ -1469,6 +1524,7 @@ open_verify (const char *name, int fd,
ElfW(Ehdr) *ehdr;
ElfW(Phdr) *phdr, *ph;
ElfW(Word) *abi_note;
ElfW(Word) *abi_note_malloced = NULL;
unsigned int osversion;
size_t maplength;
@@ -1640,10 +1696,25 @@ open_verify (const char *name, int fd,
abi_note = (void *) (fbp->buf + ph->p_offset);
else
{
abi_note = alloca (size);
/* Note: __libc_use_alloca is not usable here, because
thread info may not have been set up yet. */
if (size < __MAX_ALLOCA_CUTOFF)
abi_note = alloca (size);
else
{
/* There could be multiple PT_NOTEs. */
abi_note_malloced = realloc (abi_note_malloced, size);
if (abi_note_malloced == NULL)
goto read_error;
abi_note = abi_note_malloced;
}
__lseek (fd, ph->p_offset, SEEK_SET);
if (__libc_read (fd, (void *) abi_note, size) != size)
goto read_error;
{
free (abi_note_malloced);
goto read_error;
}
}
while (memcmp (abi_note, &expected_note, sizeof (expected_note)))
@@ -1678,6 +1749,7 @@ open_verify (const char *name, int fd,
break;
}
free (abi_note_malloced);
}
return fd;
+43 -5
View File
@@ -184,10 +184,36 @@ _dl_profile_fixup (
/* This is the address in the array where we store the result of previous
relocations. */
struct reloc_result *reloc_result = &l->l_reloc_result[reloc_index];
DL_FIXUP_VALUE_TYPE *resultp = &reloc_result->addr;
DL_FIXUP_VALUE_TYPE value = *resultp;
if (DL_FIXUP_VALUE_CODE_ADDR (value) == 0)
/* CONCURRENCY NOTES:
Multiple threads may be calling the same PLT sequence and with
LD_AUDIT enabled they will be calling into _dl_profile_fixup to
update the reloc_result with the result of the lazy resolution.
The reloc_result guard variable is reloc_init, and we use
acquire/release loads and store to it to ensure that the results of
the structure are consistent with the loaded value of the guard.
This does not fix all of the data races that occur when two or more
threads read reloc_result->reloc_init with a value of zero and read
and write to that reloc_result concurrently. The expectation is
generally that while this is a data race it works because the
threads write the same values. Until the data races are fixed
there is a potential for problems to arise from these data races.
The reloc result updates should happen in parallel but there should
be an atomic RMW which does the final update to the real result
entry (see bug 23790).
The following code uses reloc_result->init set to 0 to indicate if it is
the first time this object is being relocated, otherwise 1 which
indicates the object has already been relocated.
Reading/Writing from/to reloc_result->reloc_init must not happen
before previous writes to reloc_result complete as they could
end-up with an incomplete struct. */
DL_FIXUP_VALUE_TYPE value;
unsigned int init = atomic_load_acquire (&reloc_result->init);
if (init == 0)
{
/* This is the first time we have to relocate this object. */
const ElfW(Sym) *const symtab
@@ -349,19 +375,31 @@ _dl_profile_fixup (
/* Store the result for later runs. */
if (__glibc_likely (! GLRO(dl_bind_not)))
*resultp = value;
{
reloc_result->addr = value;
/* Guarantee all previous writes complete before
init is updated. See CONCURRENCY NOTES earlier */
atomic_store_release (&reloc_result->init, 1);
}
init = 1;
}
else
value = reloc_result->addr;
/* By default we do not call the pltexit function. */
long int framesize = -1;
#ifdef SHARED
/* Auditing checkpoint: report the PLT entering and allow the
auditors to change the value. */
if (DL_FIXUP_VALUE_CODE_ADDR (value) != 0 && GLRO(dl_naudit) > 0
if (GLRO(dl_naudit) > 0
/* Don't do anything if no auditor wants to intercept this call. */
&& (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
{
/* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
initialized earlier in this function or in another thread. */
assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
l_info[DT_SYMTAB])
+ reloc_result->boundndx);
+7
View File
@@ -2835,6 +2835,13 @@ enum
#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
/* AArch64 specific values for the Dyn d_tag field. */
#define DT_AARCH64_VARIANT_PCS (DT_LOPROC + 5)
#define DT_AARCH64_NUM 6
/* AArch64 specific values for the st_other field. */
#define STO_AARCH64_VARIANT_PCS 0x80
/* ARM relocs. */
#define R_ARM_NONE 0 /* No reloc */
+40 -74
View File
@@ -23,10 +23,6 @@
#define EW_(e, w, t) EW__(e, w, _##t)
#define EW__(e, w, t) e##w##t
#define pldd_assert(name, exp) \
typedef int __assert_##name[((exp) != 0) - 1]
struct E(link_map)
{
EW(Addr) l_addr;
@@ -39,12 +35,12 @@ struct E(link_map)
EW(Addr) l_libname;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (l_addr, (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr)));
pldd_assert (l_name, (offsetof (struct link_map, l_name)
== offsetof (struct E(link_map), l_name)));
pldd_assert (l_next, (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next)));
_Static_assert (offsetof (struct link_map, l_addr)
== offsetof (struct E(link_map), l_addr), "l_addr");
_Static_assert (offsetof (struct link_map, l_name)
== offsetof (struct E(link_map), l_name), "l_name");
_Static_assert (offsetof (struct link_map, l_next)
== offsetof (struct E(link_map), l_next), "l_next");
#endif
@@ -54,10 +50,10 @@ struct E(libname_list)
EW(Addr) next;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (name, (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name)));
pldd_assert (next, (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next)));
_Static_assert (offsetof (struct libname_list, name)
== offsetof (struct E(libname_list), name), "name");
_Static_assert (offsetof (struct libname_list, next)
== offsetof (struct E(libname_list), next), "next");
#endif
struct E(r_debug)
@@ -69,16 +65,17 @@ struct E(r_debug)
EW(Addr) r_map;
};
#if CLASS == __ELF_NATIVE_CLASS
pldd_assert (r_version, (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version)));
pldd_assert (r_map, (offsetof (struct r_debug, r_map)
== offsetof (struct E(r_debug), r_map)));
_Static_assert (offsetof (struct r_debug, r_version)
== offsetof (struct E(r_debug), r_version), "r_version");
_Static_assert (offsetof (struct r_debug, r_map)
== offsetof (struct E(r_debug), r_map), "r_map");
#endif
static int
E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
E(find_maps) (const char *exe, int memfd, pid_t pid, void *auxv,
size_t auxv_size)
{
EW(Addr) phdr = 0;
unsigned int phnum = 0;
@@ -104,12 +101,9 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (phdr == 0 || phnum == 0 || phent == 0)
error (EXIT_FAILURE, 0, gettext ("cannot find program header of process"));
EW(Phdr) *p = alloca (phnum * phent);
if (pread64 (memfd, p, phnum * phent, phdr) != phnum * phent)
{
error (0, 0, gettext ("cannot read program header"));
return EXIT_FAILURE;
}
EW(Phdr) *p = xmalloc (phnum * phent);
if (pread (memfd, p, phnum * phent, phdr) != phnum * phent)
error (EXIT_FAILURE, 0, gettext ("cannot read program header"));
/* Determine the load offset. We need this for interpreting the
other program header entries so we do this in a separate loop.
@@ -129,24 +123,18 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (p[i].p_type == PT_DYNAMIC)
{
EW(Dyn) *dyn = xmalloc (p[i].p_filesz);
if (pread64 (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
if (pread (memfd, dyn, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
{
error (0, 0, gettext ("cannot read dynamic section"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read dynamic section"));
/* Search for the DT_DEBUG entry. */
for (unsigned int j = 0; j < p[i].p_filesz / sizeof (EW(Dyn)); ++j)
if (dyn[j].d_tag == DT_DEBUG && dyn[j].d_un.d_ptr != 0)
{
struct E(r_debug) r;
if (pread64 (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
if (pread (memfd, &r, sizeof (r), dyn[j].d_un.d_ptr)
!= sizeof (r))
{
error (0, 0, gettext ("cannot read r_debug"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read r_debug"));
if (r.r_map != 0)
{
@@ -160,13 +148,10 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
else if (p[i].p_type == PT_INTERP)
{
interp = alloca (p[i].p_filesz);
if (pread64 (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
interp = xmalloc (p[i].p_filesz);
if (pread (memfd, interp, p[i].p_filesz, offset + p[i].p_vaddr)
!= p[i].p_filesz)
{
error (0, 0, gettext ("cannot read program interpreter"));
return EXIT_FAILURE;
}
error (EXIT_FAILURE, 0, gettext ("cannot read program interpreter"));
}
if (list == 0)
@@ -174,14 +159,16 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
if (interp == NULL)
{
// XXX check whether the executable itself is the loader
return EXIT_FAILURE;
exit (EXIT_FAILURE);
}
// XXX perhaps try finding ld.so and _r_debug in it
return EXIT_FAILURE;
exit (EXIT_FAILURE);
}
free (p);
free (interp);
/* Print the PID and program name first. */
printf ("%lu:\t%s\n", (unsigned long int) pid, exe);
@@ -192,47 +179,27 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
do
{
struct E(link_map) m;
if (pread64 (memfd, &m, sizeof (m), list) != sizeof (m))
{
error (0, 0, gettext ("cannot read link map"));
status = EXIT_FAILURE;
goto out;
}
if (pread (memfd, &m, sizeof (m), list) != sizeof (m))
error (EXIT_FAILURE, 0, gettext ("cannot read link map"));
EW(Addr) name_offset = m.l_name;
again:
while (1)
{
ssize_t n = pread64 (memfd, tmpbuf.data, tmpbuf.length, name_offset);
ssize_t n = pread (memfd, tmpbuf.data, tmpbuf.length, name_offset);
if (n == -1)
{
error (0, 0, gettext ("cannot read object name"));
status = EXIT_FAILURE;
goto out;
}
error (EXIT_FAILURE, 0, gettext ("cannot read object name"));
if (memchr (tmpbuf.data, '\0', n) != NULL)
break;
if (!scratch_buffer_grow (&tmpbuf))
{
error (0, 0, gettext ("cannot allocate buffer for object name"));
status = EXIT_FAILURE;
goto out;
}
error (EXIT_FAILURE, 0,
gettext ("cannot allocate buffer for object name"));
}
if (((char *)tmpbuf.data)[0] == '\0' && name_offset == m.l_name
&& m.l_libname != 0)
{
/* Try the l_libname element. */
struct E(libname_list) ln;
if (pread64 (memfd, &ln, sizeof (ln), m.l_libname) == sizeof (ln))
{
name_offset = ln.name;
goto again;
}
}
/* The m.l_name and m.l_libname.name for loader linkmap points to same
values (since BZ#387 fix). Trying to use l_libname name as the
shared object name might lead to an infinite loop (BZ#18035). */
/* Skip over the executable. */
if (((char *)tmpbuf.data)[0] != '\0')
@@ -242,7 +209,6 @@ E(find_maps) (pid_t pid, void *auxv, size_t auxv_size)
}
while (list != 0);
out:
scratch_buffer_free (&tmpbuf);
return status;
}
+30 -34
View File
@@ -17,23 +17,17 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <alloca.h>
#define _FILE_OFFSET_BITS 64
#include <argp.h>
#include <assert.h>
#include <dirent.h>
#include <elf.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <libintl.h>
#include <link.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <scratch_buffer.h>
@@ -76,14 +70,9 @@ static struct argp argp =
options, parse_opt, args_doc, doc, NULL, more_help, NULL
};
// File descriptor of /proc/*/mem file.
static int memfd;
/* Name of the executable */
static char *exe;
/* Local functions. */
static int get_process_info (int dfd, long int pid);
static int get_process_info (const char *exe, int dfd, long int pid);
static void wait_for_ptrace_stop (long int pid);
@@ -102,8 +91,10 @@ main (int argc, char *argv[])
return 1;
}
assert (sizeof (pid_t) == sizeof (int)
|| sizeof (pid_t) == sizeof (long int));
_Static_assert (sizeof (pid_t) == sizeof (int)
|| sizeof (pid_t) == sizeof (long int),
"sizeof (pid_t) != sizeof (int) or sizeof (long int)");
char *endp;
errno = 0;
long int pid = strtol (argv[remaining], &endp, 10);
@@ -119,25 +110,24 @@ main (int argc, char *argv[])
if (dfd == -1)
error (EXIT_FAILURE, errno, gettext ("cannot open %s"), buf);
struct scratch_buffer exebuf;
scratch_buffer_init (&exebuf);
/* Name of the executable */
struct scratch_buffer exe;
scratch_buffer_init (&exe);
ssize_t nexe;
while ((nexe = readlinkat (dfd, "exe",
exebuf.data, exebuf.length)) == exebuf.length)
exe.data, exe.length)) == exe.length)
{
if (!scratch_buffer_grow (&exebuf))
if (!scratch_buffer_grow (&exe))
{
nexe = -1;
break;
}
}
if (nexe == -1)
exe = (char *) "<program name undetermined>";
/* Default stack allocation is at least 1024. */
snprintf (exe.data, exe.length, "<program name undetermined>");
else
{
exe = exebuf.data;
exe[nexe] = '\0';
}
((char*)exe.data)[nexe] = '\0';
/* Stop all threads since otherwise the list of loaded modules might
change while we are reading it. */
@@ -155,8 +145,8 @@ main (int argc, char *argv[])
error (EXIT_FAILURE, errno, gettext ("cannot prepare reading %s/task"),
buf);
struct dirent64 *d;
while ((d = readdir64 (dir)) != NULL)
struct dirent *d;
while ((d = readdir (dir)) != NULL)
{
if (! isdigit (d->d_name[0]))
continue;
@@ -182,7 +172,7 @@ main (int argc, char *argv[])
wait_for_ptrace_stop (tid);
struct thread_list *newp = alloca (sizeof (*newp));
struct thread_list *newp = xmalloc (sizeof (*newp));
newp->tid = tid;
newp->next = thread_list;
thread_list = newp;
@@ -190,17 +180,22 @@ main (int argc, char *argv[])
closedir (dir);
int status = get_process_info (dfd, pid);
if (thread_list == NULL)
error (EXIT_FAILURE, 0, gettext ("no valid %s/task entries"), buf);
int status = get_process_info (exe.data, dfd, pid);
assert (thread_list != NULL);
do
{
ptrace (PTRACE_DETACH, thread_list->tid, NULL, NULL);
struct thread_list *prev = thread_list;
thread_list = thread_list->next;
free (prev);
}
while (thread_list != NULL);
close (dfd);
scratch_buffer_free (&exe);
return status;
}
@@ -281,9 +276,10 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
static int
get_process_info (int dfd, long int pid)
get_process_info (const char *exe, int dfd, long int pid)
{
memfd = openat (dfd, "mem", O_RDONLY);
/* File descriptor of /proc/<pid>/mem file. */
int memfd = openat (dfd, "mem", O_RDONLY);
if (memfd == -1)
goto no_info;
@@ -333,9 +329,9 @@ get_process_info (int dfd, long int pid)
int retval;
if (e_ident[EI_CLASS] == ELFCLASS32)
retval = find_maps32 (pid, auxv, auxv_size);
retval = find_maps32 (exe, memfd, pid, auxv, auxv_size);
else
retval = find_maps64 (pid, auxv, auxv_size);
retval = find_maps64 (exe, memfd, pid, auxv, auxv_size);
free (auxv);
close (memfd);
+26
View File
@@ -0,0 +1,26 @@
/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify()
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This creates a .so with 8MiB PT_NOTE segment.
On a typical Linux system with 8MiB "ulimit -s", that was enough
to trigger stack overflow in open_verify. */
.pushsection .note.big,"a"
.balign 4
.fill 8*1024*1024, 1, 0
.popsection
@@ -1,5 +1,5 @@
/* Test the fallback implementation of copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
/* Bug 20419: test for stack overflow in elf/dl-load.c open_verify()
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,15 +16,11 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Get the declaration of the official copy_of_range function. */
#include <unistd.h>
/* This file must be run from within a directory called "elf". */
/* Compile a local version of copy_file_range. */
#define COPY_FILE_RANGE_DECL static
#define COPY_FILE_RANGE copy_file_range_compat
#include <io/copy_file_range-compat.c>
/* Re-use the test, but run it against copy_file_range_compat defined
above. */
#define copy_file_range copy_file_range_compat
#include "tst-copy_file_range.c"
int main (int argc, char *argv[])
{
/* Nothing to do here: merely linking against tst-big-note-lib.so triggers
the bug. */
return 0;
}
+16 -2
View File
@@ -26,7 +26,7 @@ headers = iconv.h gconv.h
routines = iconv_open iconv iconv_close \
gconv_open gconv gconv_close gconv_db gconv_conf \
gconv_builtin gconv_simple gconv_trans gconv_cache
routines += gconv_dl
routines += gconv_dl gconv_charset
vpath %.c ../locale/programs ../intl
@@ -43,7 +43,8 @@ CFLAGS-charmap.c += -DCHARMAP_PATH='"$(i18ndir)/charmaps"' \
CFLAGS-linereader.c += -DNO_TRANSLITERATION
CFLAGS-simple-hash.c += -I../locale
tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6
tests = tst-iconv1 tst-iconv2 tst-iconv3 tst-iconv4 tst-iconv5 tst-iconv6 \
tst-iconv7 tst-iconv8 tst-iconv-opt
others = iconv_prog iconvconfig
install-others-programs = $(inst_bindir)/iconv
@@ -60,6 +61,7 @@ include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
ifeq ($(run-built-tests),yes)
xtests-special += $(objpfx)test-iconvconfig.out
tests-special += $(objpfx)tst-iconv_prog.out
endif
# Make a copy of the file because gconv module names are constructed
@@ -78,6 +80,13 @@ endif
include ../Rules
ifeq ($(run-built-tests),yes)
LOCALES := en_US.UTF-8
include ../gen-locales.mk
$(objpfx)tst-iconv-opt.out: $(gen-locales)
endif
$(inst_bindir)/iconv: $(objpfx)iconv_prog $(+force)
$(do-install-program)
@@ -92,3 +101,8 @@ $(objpfx)test-iconvconfig.out: /dev/null $(objpfx)iconvconfig
cmp $$tmp $(inst_gconvdir)/gconv-modules.cache; \
rm -f $$tmp) > $@; \
$(evaluate-test)
$(objpfx)tst-iconv_prog.out: tst-iconv_prog.sh $(objpfx)iconv_prog
$(BASH) $< $(common-objdir) '$(test-wrapper-env)' \
'$(run-program-env)' > $@; \
$(evaluate-test)
+3
View File
@@ -7,6 +7,9 @@ libc {
# functions shared with iconv program
__gconv_get_alias_db; __gconv_get_cache; __gconv_get_modules_db;
# functions used elsewhere in glibc
__gconv_open; __gconv_create_spec; __gconv_destroy_spec;
# function used by the gconv modules
__gconv_transliterate;
}
+228
View File
@@ -0,0 +1,228 @@
/* Charset name normalization.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <stdlib.h>
#include <ctype.h>
#include <locale.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include "gconv_int.h"
#include "gconv_charset.h"
/* This function returns a pointer to the last suffix in a conversion code
string. Valid suffixes matched by this function are of the form: '/' or ','
followed by arbitrary text that doesn't contain '/' or ','. It does not
edit the string in any way. The caller is expected to parse the suffix and
remove it (by e.g. truncating the string) before the next call. */
static char *
find_suffix (char *s)
{
/* The conversion code is in the form of a triplet, separated by '/' chars.
The third component of the triplet contains suffixes. If we don't have two
slashes, we don't have a suffix. */
int slash_count = 0;
char *suffix_term = NULL;
for (int i = 0; s[i] != '\0'; i++)
switch (s[i])
{
case '/':
slash_count++;
/* Fallthrough */
case ',':
suffix_term = &s[i];
}
if (slash_count >= 2)
return suffix_term;
return NULL;
}
struct gconv_parsed_code
{
char *code;
bool translit;
bool ignore;
};
/* This function parses an iconv_open encoding PC.CODE, strips any suffixes
(such as TRANSLIT or IGNORE) from it and sets corresponding flags in it. */
static void
gconv_parse_code (struct gconv_parsed_code *pc)
{
pc->translit = false;
pc->ignore = false;
while (1)
{
/* First drop any trailing whitespaces and separators. */
size_t len = strlen (pc->code);
while ((len > 0)
&& (isspace (pc->code[len - 1])
|| pc->code[len - 1] == ','
|| pc->code[len - 1] == '/'))
len--;
pc->code[len] = '\0';
if (len == 0)
return;
char * suffix = find_suffix (pc->code);
if (suffix == NULL)
{
/* At this point, we have processed and removed all suffixes from the
code and what remains of the code is suffix free. */
return;
}
else
{
/* A suffix is processed from the end of the code array going
backwards, one suffix at a time. The suffix is an index into the
code character array and points to: one past the end of the code
and any unprocessed suffixes, and to the beginning of the suffix
currently being processed during this iteration. We must process
this suffix and then drop it from the code by terminating the
preceding text with NULL.
We want to allow and recognize suffixes such as:
"/TRANSLIT" i.e. single suffix
"//TRANSLIT" i.e. single suffix and multiple separators
"//TRANSLIT/IGNORE" i.e. suffixes separated by "/"
"/TRANSLIT//IGNORE" i.e. suffixes separated by "//"
"//IGNORE,TRANSLIT" i.e. suffixes separated by ","
"//IGNORE," i.e. trailing ","
"//TRANSLIT/" i.e. trailing "/"
"//TRANSLIT//" i.e. trailing "//"
"/" i.e. empty suffix.
Unknown suffixes are silently discarded and ignored. */
if ((__strcasecmp_l (suffix,
GCONV_TRIPLE_SEPARATOR
GCONV_TRANSLIT_SUFFIX,
_nl_C_locobj_ptr) == 0)
|| (__strcasecmp_l (suffix,
GCONV_SUFFIX_SEPARATOR
GCONV_TRANSLIT_SUFFIX,
_nl_C_locobj_ptr) == 0))
pc->translit = true;
if ((__strcasecmp_l (suffix,
GCONV_TRIPLE_SEPARATOR
GCONV_IGNORE_ERRORS_SUFFIX,
_nl_C_locobj_ptr) == 0)
|| (__strcasecmp_l (suffix,
GCONV_SUFFIX_SEPARATOR
GCONV_IGNORE_ERRORS_SUFFIX,
_nl_C_locobj_ptr) == 0))
pc->ignore = true;
/* We just processed this suffix. We can now drop it from the
code string by truncating it at the suffix's position. */
suffix[0] = '\0';
}
}
}
/* This function accepts the charset names of the source and destination of the
conversion and populates *conv_spec with an equivalent conversion
specification that may later be used by __gconv_open. The charset names
might contain options in the form of suffixes that alter the conversion,
e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
and truncating any suffix options in fromcode, and processing and truncating
any suffix options in tocode. Supported suffix options ("TRANSLIT" or
"IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
to be set to true. Unrecognized suffix options are silently discarded. If
the function succeeds, it returns conv_spec back to the caller. It returns
NULL upon failure. conv_spec must be allocated and freed by the caller. */
struct gconv_spec *
__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
const char *tocode)
{
struct gconv_parsed_code pfc, ptc;
struct gconv_spec *ret = NULL;
pfc.code = __strdup (fromcode);
ptc.code = __strdup (tocode);
if ((pfc.code == NULL)
|| (ptc.code == NULL))
goto out;
gconv_parse_code (&pfc);
gconv_parse_code (&ptc);
/* We ignore suffixes in the fromcode because that is how the current
implementation has always handled them. Only suffixes in the tocode are
processed and handled. The reality is that invalid input in the input
character set should only be ignored if the fromcode specifies IGNORE.
The current implementation ignores invalid intput in the input character
set if the tocode contains IGNORE. We preserve this behavior for
backwards compatibility. In the future we may split the handling of
IGNORE to allow a finer grained specification of ignorning invalid input
and/or ignoring invalid output. */
conv_spec->translit = ptc.translit;
conv_spec->ignore = ptc.ignore;
/* 3 extra bytes because 1 extra for '\0', and 2 extra so strip might
be able to add one or two trailing '/' characters if necessary. */
conv_spec->fromcode = malloc (strlen (fromcode) + 3);
if (conv_spec->fromcode == NULL)
goto out;
conv_spec->tocode = malloc (strlen (tocode) + 3);
if (conv_spec->tocode == NULL)
{
free (conv_spec->fromcode);
conv_spec->fromcode = NULL;
goto out;
}
/* Strip unrecognized characters and ensure that the code has two '/'
characters as per conversion code triplet specification. */
strip (conv_spec->fromcode, pfc.code);
strip (conv_spec->tocode, ptc.code);
ret = conv_spec;
out:
free (pfc.code);
free (ptc.code);
return ret;
}
libc_hidden_def (__gconv_create_spec)
void
__gconv_destroy_spec (struct gconv_spec *conv_spec)
{
free (conv_spec->fromcode);
free (conv_spec->tocode);
return;
}
libc_hidden_def (__gconv_destroy_spec)
+33 -1
View File
@@ -19,9 +19,41 @@
#include <ctype.h>
#include <locale.h>
#include <stdbool.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include "gconv_int.h"
static void
/* An iconv encoding is in the form of a triplet, with parts separated by
a '/' character. The first part is the standard name, the second part is
the character set, and the third part is the error handler. If the first
part is sufficient to identify both the standard and the character set
then the second part can be empty e.g. UTF-8//. If the first part is not
sufficient to identify both the standard and the character set then the
second part is required e.g. ISO-10646/UTF8/. If neither the first or
second parts are provided e.g. //, then the current locale is used.
The actual values used in the first and second parts are not entirely
relevant to the implementation. The values themselves are used in a hash
table to lookup modules and so the naming convention of the first two parts
is somewhat arbitrary and only helps locate the entries in the cache.
The third part is the error handler and is comprised of a ',' or '/'
separated list of suffixes. Currently, we support "TRANSLIT" for
transliteration and "IGNORE" for ignoring conversion errors due to
unrecognized input characters. */
#define GCONV_TRIPLE_SEPARATOR "/"
#define GCONV_SUFFIX_SEPARATOR ","
#define GCONV_TRANSLIT_SUFFIX "TRANSLIT"
#define GCONV_IGNORE_ERRORS_SUFFIX "IGNORE"
/* This function copies in-order, characters from the source 's' that are
either alpha-numeric or one in one of these: "_-.,:/" - into the destination
'wp' while dropping all other characters. In the process, it converts all
alphabetical characters to upper case. It then appends up to two '/'
characters so that the total number of '/'es in the destination is 2. */
static inline void __attribute__ ((unused, always_inline))
strip (char *wp, const char *s)
{
int slash_count = 0;
+36 -4
View File
@@ -92,6 +92,15 @@ struct gconv_module
};
/* The specification of the conversion that needs to be performed. */
struct gconv_spec
{
char *fromcode;
char *tocode;
bool translit;
bool ignore;
};
/* Flags for `gconv_open'. */
enum
{
@@ -154,10 +163,33 @@ __libc_lock_define (extern, __gconv_lock attribute_hidden)
})
/* Return in *HANDLE decriptor for transformation from FROMSET to TOSET. */
extern int __gconv_open (const char *toset, const char *fromset,
__gconv_t *handle, int flags)
attribute_hidden;
/* Return in *HANDLE, a decriptor for the transformation. The function expects
the specification of the transformation in the structure pointed to by
CONV_SPEC. It only reads *CONV_SPEC and does not take ownership of it. */
extern int __gconv_open (struct gconv_spec *conv_spec,
__gconv_t *handle, int flags);
libc_hidden_proto (__gconv_open)
/* This function accepts the charset names of the source and destination of the
conversion and populates *conv_spec with an equivalent conversion
specification that may later be used by __gconv_open. The charset names
might contain options in the form of suffixes that alter the conversion,
e.g. "ISO-10646/UTF-8/TRANSLIT". It processes the charset names, ignoring
and truncating any suffix options in fromcode, and processing and truncating
any suffix options in tocode. Supported suffix options ("TRANSLIT" or
"IGNORE") when found in tocode lead to the corresponding flag in *conv_spec
to be set to true. Unrecognized suffix options are silently discarded. If
the function succeeds, it returns conv_spec back to the caller. It returns
NULL upon failure. */
extern struct gconv_spec *
__gconv_create_spec (struct gconv_spec *conv_spec, const char *fromcode,
const char *tocode);
libc_hidden_proto (__gconv_create_spec)
/* This function frees all heap memory allocated by __gconv_create_spec. */
extern void
__gconv_destroy_spec (struct gconv_spec *conv_spec);
libc_hidden_proto (__gconv_destroy_spec)
/* Free resources associated with transformation descriptor CD. */
extern int __gconv_close (__gconv_t cd)
+13 -51
View File
@@ -27,7 +27,7 @@
int
__gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
__gconv_open (struct gconv_spec *conv_spec, __gconv_t *handle,
int flags)
{
struct __gconv_step *steps;
@@ -36,77 +36,38 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
size_t cnt = 0;
int res;
int conv_flags = 0;
const char *errhand;
const char *ignore;
bool translit = false;
char *tocode, *fromcode;
/* Find out whether any error handling method is specified. */
errhand = strchr (toset, '/');
if (errhand != NULL)
errhand = strchr (errhand + 1, '/');
if (__glibc_likely (errhand != NULL))
{
if (*++errhand == '\0')
errhand = NULL;
else
{
/* Make copy without the error handling description. */
char *newtoset = (char *) alloca (errhand - toset + 1);
char *tok;
char *ptr = NULL /* Work around a bogus warning */;
translit = conv_spec->translit;
newtoset[errhand - toset] = '\0';
toset = memcpy (newtoset, toset, errhand - toset);
if (conv_spec->ignore)
conv_flags |= __GCONV_IGNORE_ERRORS;
/* Find the appropriate transliteration handlers. */
tok = strdupa (errhand);
tok = __strtok_r (tok, ",", &ptr);
while (tok != NULL)
{
if (__strcasecmp_l (tok, "TRANSLIT", _nl_C_locobj_ptr) == 0)
translit = true;
else if (__strcasecmp_l (tok, "IGNORE", _nl_C_locobj_ptr) == 0)
/* Set the flag to ignore all errors. */
conv_flags |= __GCONV_IGNORE_ERRORS;
tok = __strtok_r (NULL, ",", &ptr);
}
}
}
/* For the source character set we ignore the error handler specification.
XXX Is this really always the best? */
ignore = strchr (fromset, '/');
if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
&& *++ignore != '\0')
{
char *newfromset = (char *) alloca (ignore - fromset + 1);
newfromset[ignore - fromset] = '\0';
fromset = memcpy (newfromset, fromset, ignore - fromset);
}
tocode = conv_spec->tocode;
fromcode = conv_spec->fromcode;
/* If the string is empty define this to mean the charset of the
currently selected locale. */
if (strcmp (toset, "//") == 0)
if (strcmp (tocode, "//") == 0)
{
const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
size_t len = strlen (codeset);
char *dest;
toset = dest = (char *) alloca (len + 3);
tocode = dest = (char *) alloca (len + 3);
memcpy (__mempcpy (dest, codeset, len), "//", 3);
}
if (strcmp (fromset, "//") == 0)
if (strcmp (fromcode, "//") == 0)
{
const char *codeset = _NL_CURRENT (LC_CTYPE, CODESET);
size_t len = strlen (codeset);
char *dest;
fromset = dest = (char *) alloca (len + 3);
fromcode = dest = (char *) alloca (len + 3);
memcpy (__mempcpy (dest, codeset, len), "//", 3);
}
res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
res = __gconv_find_transform (tocode, fromcode, &steps, &nsteps, flags);
if (res == __GCONV_OK)
{
/* Allocate room for handle. */
@@ -205,3 +166,4 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
*handle = result;
return res;
}
libc_hidden_def (__gconv_open)
+24 -24
View File
@@ -76,7 +76,7 @@ __attribute ((always_inline))
internal_ucs4_loop (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp, const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
@@ -120,7 +120,8 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
@@ -169,7 +170,8 @@ internal_ucs4_loop_single (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
mbstate_t *state = step_data->__statep;
@@ -231,17 +233,15 @@ __attribute ((always_inline))
ucs4_internal_loop (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp, const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -298,17 +298,16 @@ ucs4_internal_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[0] > 0x80))
{
@@ -368,7 +367,8 @@ ucs4_internal_loop_single (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
mbstate_t *state = step_data->__statep;
@@ -443,7 +443,7 @@ __attribute ((always_inline))
internal_ucs4le_loop (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp, const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
@@ -488,7 +488,8 @@ internal_ucs4le_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
const unsigned char *inptr = *inptrp;
@@ -540,7 +541,8 @@ internal_ucs4le_loop_single (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
mbstate_t *state = step_data->__statep;
@@ -601,17 +603,15 @@ __attribute ((always_inline))
ucs4le_internal_loop (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp, const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp, const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
uint32_t inval;
@@ -671,17 +671,16 @@ ucs4le_internal_loop_unaligned (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
int flags = step_data->__flags;
const unsigned char *inptr = *inptrp;
unsigned char *outptr = *outptrp;
size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
int result;
size_t cnt;
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
for (; inptr + 4 <= inend && outptr + 4 <= outend; inptr += 4)
{
if (__glibc_unlikely (inptr[3] > 0x80))
{
@@ -745,7 +744,8 @@ ucs4le_internal_loop_single (struct __gconv_step *step,
struct __gconv_step_data *step_data,
const unsigned char **inptrp,
const unsigned char *inend,
unsigned char **outptrp, unsigned char *outend,
unsigned char **outptrp,
const unsigned char *outend,
size_t *irreversible)
{
mbstate_t *state = step_data->__statep;
+7 -41
View File
@@ -31,49 +31,15 @@
iconv_t
iconv_open (const char *tocode, const char *fromcode)
{
/* Normalize the name. We remove all characters beside alpha-numeric,
'_', '-', '/', '.', and ':'. */
size_t tocode_len = strlen (tocode) + 3;
char *tocode_conv;
bool tocode_usealloca = __libc_use_alloca (tocode_len);
if (tocode_usealloca)
tocode_conv = (char *) alloca (tocode_len);
else
{
tocode_conv = (char *) malloc (tocode_len);
if (tocode_conv == NULL)
return (iconv_t) -1;
}
strip (tocode_conv, tocode);
tocode = (tocode_conv[2] == '\0' && tocode[0] != '\0'
? upstr (tocode_conv, tocode) : tocode_conv);
size_t fromcode_len = strlen (fromcode) + 3;
char *fromcode_conv;
bool fromcode_usealloca = __libc_use_alloca (fromcode_len);
if (fromcode_usealloca)
fromcode_conv = (char *) alloca (fromcode_len);
else
{
fromcode_conv = (char *) malloc (fromcode_len);
if (fromcode_conv == NULL)
{
if (! tocode_usealloca)
free (tocode_conv);
return (iconv_t) -1;
}
}
strip (fromcode_conv, fromcode);
fromcode = (fromcode_conv[2] == '\0' && fromcode[0] != '\0'
? upstr (fromcode_conv, fromcode) : fromcode_conv);
__gconv_t cd;
int res = __gconv_open (tocode, fromcode, &cd, 0);
struct gconv_spec conv_spec;
if (! fromcode_usealloca)
free (fromcode_conv);
if (! tocode_usealloca)
free (tocode_conv);
if (__gconv_create_spec (&conv_spec, fromcode, tocode) == NULL)
return (iconv_t) -1;
int res = __gconv_open (&conv_spec, &cd, 0);
__gconv_destroy_spec (&conv_spec);
if (__builtin_expect (res, __GCONV_OK) != __GCONV_OK)
{
+23 -40
View File
@@ -39,6 +39,7 @@
#include <gconv_int.h>
#include "iconv_prog.h"
#include "iconvconfig.h"
#include "gconv_charset.h"
/* Get libc version number. */
#include "../version.h"
@@ -118,8 +119,7 @@ main (int argc, char *argv[])
{
int status = EXIT_SUCCESS;
int remaining;
iconv_t cd;
const char *orig_to_code;
__gconv_t cd;
struct charmap_t *from_charmap = NULL;
struct charmap_t *to_charmap = NULL;
@@ -139,39 +139,6 @@ main (int argc, char *argv[])
exit (EXIT_SUCCESS);
}
/* If we have to ignore errors make sure we use the appropriate name for
the to-character-set. */
orig_to_code = to_code;
if (omit_invalid)
{
const char *errhand = strchrnul (to_code, '/');
int nslash = 2;
char *newp;
char *cp;
if (*errhand == '/')
{
--nslash;
errhand = strchrnul (errhand + 1, '/');
if (*errhand == '/')
{
--nslash;
errhand = strchr (errhand, '\0');
}
}
newp = (char *) alloca (errhand - to_code + nslash + 7 + 1);
cp = mempcpy (newp, to_code, errhand - to_code);
while (nslash-- > 0)
*cp++ = '/';
if (cp[-1] != '/')
*cp++ = ',';
memcpy (cp, "IGNORE", sizeof ("IGNORE"));
to_code = newp;
}
/* POSIX 1003.2b introduces a silly thing: the arguments to -t anf -f
can be file names of charmaps. In this case iconv will have to read
those charmaps and use them to do the conversion. But there are
@@ -184,10 +151,10 @@ main (int argc, char *argv[])
file. */
from_charmap = charmap_read (from_code, /*0, 1*/1, 0, 0, 0);
if (strchr (orig_to_code, '/') != NULL)
if (strchr (to_code, '/') != NULL)
/* The to-name might be a charmap file name. Try reading the
file. */
to_charmap = charmap_read (orig_to_code, /*0, 1,*/1, 0, 0, 0);
to_charmap = charmap_read (to_code, /*0, 1,*/1, 0, 0, 0);
/* At this point we have to handle two cases. The first one is
@@ -201,9 +168,25 @@ main (int argc, char *argv[])
argc, remaining, argv, output_file);
else
{
struct gconv_spec conv_spec;
int res;
if (__gconv_create_spec (&conv_spec, from_code, to_code) == NULL)
{
error (EXIT_FAILURE, errno,
_("failed to start conversion processing"));
exit (1);
}
if (omit_invalid)
conv_spec.ignore = true;
/* Let's see whether we have these coded character sets. */
cd = iconv_open (to_code, from_code);
if (cd == (iconv_t) -1)
res = __gconv_open (&conv_spec, &cd, 0);
__gconv_destroy_spec (&conv_spec);
if (res != __GCONV_OK)
{
if (errno == EINVAL)
{
@@ -221,7 +204,7 @@ main (int argc, char *argv[])
const char *from_pretty =
(from_code[0] ? from_code : nl_langinfo (CODESET));
const char *to_pretty =
(orig_to_code[0] ? orig_to_code : nl_langinfo (CODESET));
(to_code[0] ? to_code : nl_langinfo (CODESET));
if (from_wrong)
{
+28 -7
View File
@@ -83,6 +83,11 @@
RESET_INPUT_BUFFER If the input character sets allow this the macro
can be defined to reset the input buffer pointers
to cover only those characters up to the error.
Note that if the conversion has skipped over
irreversible characters (due to
__GCONV_IGNORE_ERRORS) there is no longer a direct
correspondence between input and output pointers,
and this macro is not called.
FUNCTION_NAME if not set the conversion function is named `gconv'.
@@ -597,6 +602,12 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
inptr = *inptrp;
/* The outbuf buffer is empty. */
outstart = outbuf;
#ifdef RESET_INPUT_BUFFER
/* Remember how many irreversible characters were skipped before
this round. */
size_t loop_irreversible
= lirreversible + (irreversible ? *irreversible : 0);
#endif
#ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (1);
@@ -671,8 +682,16 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
if (__glibc_unlikely (outerr != outbuf))
{
#ifdef RESET_INPUT_BUFFER
RESET_INPUT_BUFFER;
#else
/* RESET_INPUT_BUFFER can only work when there were
no new irreversible characters skipped during
this round. */
if (loop_irreversible
== lirreversible + (irreversible ? *irreversible : 0))
{
RESET_INPUT_BUFFER;
goto done_reset;
}
#endif
/* We have a problem in one of the functions below.
Undo the conversion upto the error point. */
size_t nstatus __attribute__ ((unused));
@@ -682,9 +701,9 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
outbuf = outstart;
/* Restore the state. */
# ifdef SAVE_RESET_STATE
#ifdef SAVE_RESET_STATE
SAVE_RESET_STATE (0);
# endif
#endif
if (__glibc_likely (!unaligned))
{
@@ -701,7 +720,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
lirreversiblep
EXTRA_LOOP_ARGS);
}
# if POSSIBLY_UNALIGNED
#if POSSIBLY_UNALIGNED
else
{
if (FROM_DIRECTION)
@@ -720,7 +739,7 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
lirreversiblep
EXTRA_LOOP_ARGS);
}
# endif
#endif
/* We must run out of output buffer space in this
rerun. */
@@ -731,9 +750,11 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
the invocation counter. */
if (__glibc_unlikely (outbuf == outstart))
--data->__invocation_counter;
#endif /* reset input buffer */
}
#ifdef RESET_INPUT_BUFFER
done_reset:
#endif
/* Change the status. */
status = result;
}
+347
View File
@@ -0,0 +1,347 @@
/* Test iconv's TRANSLIT and IGNORE option handling
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <iconv.h>
#include <locale.h>
#include <errno.h>
#include <string.h>
#include <support/support.h>
#include <support/check.h>
/* Run one iconv test. Arguments:
to: destination character set and options
from: source character set
input: input string to be converted
exp_in: expected number of bytes consumed
exp_ret: expected return value (error or number of irreversible conversions)
exp_out: expected output string
exp_err: expected value of `errno' after iconv returns. */
static void
test_iconv (const char *to, const char *from, char *input, size_t exp_in,
size_t exp_ret, const char *exp_out, int exp_err)
{
iconv_t cd;
char outbuf[500];
size_t inlen, outlen;
char *inptr, *outptr;
size_t n;
cd = iconv_open (to, from);
TEST_VERIFY (cd != (iconv_t) -1);
inlen = strlen (input);
outlen = sizeof (outbuf);
inptr = input;
outptr = outbuf;
errno = 0;
n = iconv (cd, &inptr, &inlen, &outptr, &outlen);
TEST_COMPARE (n, exp_ret);
TEST_VERIFY (inptr == input + exp_in);
TEST_COMPARE (errno, exp_err);
TEST_COMPARE_BLOB (outbuf, outptr - outbuf, exp_out, strlen (exp_out));
TEST_VERIFY (iconv_close (cd) == 0);
}
/* We test option parsing by converting UTF-8 inputs to ASCII under various
option combinations. The UTF-8 inputs fall into three categories:
- ASCII-only,
- non-ASCII,
- non-ASCII with invalid UTF-8 characters. */
/* 1. */
char ascii[] = "Just some ASCII text";
/* 2. Valid UTF-8 input and some corresponding expected outputs with various
options. The two non-ASCII characters below are accented alphabets:
an `a' then an `o'. */
char utf8[] = "UTF-8 text with \u00E1 couple \u00F3f non-ASCII characters";
char u2a[] = "UTF-8 text with ";
char u2a_translit[] = "UTF-8 text with a couple of non-ASCII characters";
char u2a_ignore[] = "UTF-8 text with couple f non-ASCII characters";
/* 3. Invalid UTF-8 input and some corresponding expected outputs. \xff is
invalid UTF-8. It's followed by some valid but non-ASCII UTF-8. */
char iutf8[] = "Invalid UTF-8 \xff\u27E6text\u27E7";
char iu2a[] = "Invalid UTF-8 ";
char iu2a_ignore[] = "Invalid UTF-8 text";
char iu2a_both[] = "Invalid UTF-8 [|text|]";
/* 4. Another invalid UTF-8 input and corresponding expected outputs. This time
the valid non-ASCII UTF-8 characters appear before the invalid \xff. */
char jutf8[] = "Invalid \u27E6UTF-8\u27E7 \xfftext";
char ju2a[] = "Invalid ";
char ju2a_translit[] = "Invalid [|UTF-8|] ";
char ju2a_ignore[] = "Invalid UTF-8 text";
char ju2a_both[] = "Invalid [|UTF-8|] text";
/* We also test option handling for character set names that have the form
"A/B". In this test, we test conversions "ISO-10646/UTF-8", and either
ISO-8859-1 or ASCII. */
/* 5. Accented 'A' and 'a' characters in ISO-8859-1 and UTF-8, and an
equivalent ASCII transliteration. */
char iso8859_1_a[] = {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, /* Accented A's. */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, /* Accented a's. */
0x00};
char utf8_a[] = "\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5"
"\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5";
char ascii_a[] = "AAAAAAaaaaaa";
/* 6. An invalid ASCII string where [0] is invalid and [1] is '~'. */
char iascii [] = {0x80, '~', '\0'};
char empty[] = "";
char ia2u_ignore[] = "~";
static int
do_test (void)
{
xsetlocale (LC_ALL, "en_US.UTF-8");
/* 0. iconv_open should gracefully fail for invalid character sets. */
TEST_VERIFY (iconv_open ("INVALID", "UTF-8") == (iconv_t) -1);
TEST_VERIFY (iconv_open ("UTF-8", "INVALID") == (iconv_t) -1);
TEST_VERIFY (iconv_open ("INVALID", "INVALID") == (iconv_t) -1);
/* 1. ASCII-only UTF-8 input should convert to ASCII with no changes: */
test_iconv ("ASCII", "UTF-8", ascii, strlen (ascii), 0, ascii, 0);
test_iconv ("ASCII//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0);
test_iconv ("ASCII//TRANSLIT", "UTF-8", ascii, strlen (ascii), 0, ascii, 0);
test_iconv ("ASCII//TRANSLIT//", "UTF-8", ascii, strlen (ascii), 0, ascii,
0);
test_iconv ("ASCII//IGNORE", "UTF-8", ascii, strlen (ascii), 0, ascii, 0);
test_iconv ("ASCII//IGNORE//", "UTF-8", ascii, strlen (ascii), 0, ascii, 0);
/* 2. Valid UTF-8 input with non-ASCII characters: */
/* EILSEQ when converted to ASCII. */
test_iconv ("ASCII", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a, EILSEQ);
/* Converted without error with TRANSLIT enabled. */
test_iconv ("ASCII//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2, u2a_translit,
0);
/* EILSEQ with IGNORE enabled. Non-ASCII chars dropped from output. */
test_iconv ("ASCII//IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1,
u2a_ignore, EILSEQ);
/* With TRANSLIT and IGNORE enabled, transliterated without error. We test
four combinations. */
test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
/* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */
test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
/* Misspellings of TRANSLIT and IGNORE are ignored, but conversion still
works while respecting any other correctly spelled options. */
test_iconv ("ASCII//T", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a,
EILSEQ);
test_iconv ("ASCII//TRANSLITERATE", "UTF-8", utf8, strlen (u2a), (size_t) -1,
u2a, EILSEQ);
test_iconv ("ASCII//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a,
EILSEQ);
test_iconv ("ASCII//IGNORED", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a,
EILSEQ);
test_iconv ("ASCII//TRANSLITERATE//IGNORED", "UTF-8", utf8, strlen (u2a),
(size_t) -1, u2a, EILSEQ);
test_iconv ("ASCII//IGNORED,TRANSLITERATE", "UTF-8", utf8, strlen (u2a),
(size_t) -1, u2a, EILSEQ);
test_iconv ("ASCII//T//I", "UTF-8", utf8, strlen (u2a), (size_t) -1, u2a,
EILSEQ);
test_iconv ("ASCII//TRANSLIT//I", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
/* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */
test_iconv ("ASCII//I//TRANSLIT", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
test_iconv ("ASCII//IGNORED,TRANSLIT", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
test_iconv ("ASCII//TRANSLIT,IGNORED", "UTF-8", utf8, strlen (utf8), 2,
u2a_translit, 0);
test_iconv ("ASCII//IGNORE,T", "UTF-8", utf8, strlen (utf8), (size_t) -1,
u2a_ignore, EILSEQ);
test_iconv ("ASCII//T,IGNORE", "UTF-8", utf8, strlen (utf8), (size_t) -1,
u2a_ignore, EILSEQ);
/* Due to bug 19519, iconv was ignoring IGNORE for the following input. */
test_iconv ("ASCII//TRANSLITERATE//IGNORE", "UTF-8", utf8, strlen (utf8),
(size_t) -1, u2a_ignore, EILSEQ);
test_iconv ("ASCII//IGNORE//TRANSLITERATE", "UTF-8", utf8, strlen (utf8),
(size_t) -1, u2a_ignore, EILSEQ);
/* 3. Invalid UTF-8 followed by some valid non-ASCII UTF-8 characters: */
/* EILSEQ; output is truncated at the first invalid UTF-8 character. */
test_iconv ("ASCII", "UTF-8", iutf8, strlen (iu2a), (size_t) -1, iu2a,
EILSEQ);
/* With TRANSLIT enabled: EILSEQ; output still truncated at the first invalid
UTF-8 character. */
test_iconv ("ASCII//TRANSLIT", "UTF-8", iutf8, strlen (iu2a), (size_t) -1,
iu2a, EILSEQ);
/* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and
valid UTF-8 non-ASCII characters. */
test_iconv ("ASCII//IGNORE", "UTF-8", iutf8, strlen (iutf8), (size_t) -1,
iu2a_ignore, EILSEQ);
/* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8
characters and transliterates valid non-ASCII UTF-8 characters. We test
four combinations. */
test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", iutf8, strlen (iutf8), 2,
iu2a_both, 0);
/* Due to bug 19519, iconv was ignoring IGNORE for the following input. */
test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", iutf8, strlen (iutf8), 2,
iu2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2,
iu2a_both, 0);
/* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */
test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", iutf8, strlen (iutf8), 2,
iu2a_both, 0);
/* 4. Invalid UTF-8 with valid non-ASCII UTF-8 chars appearing first: */
/* EILSEQ; output is truncated at the first non-ASCII character. */
test_iconv ("ASCII", "UTF-8", jutf8, strlen (ju2a), (size_t) -1, ju2a,
EILSEQ);
/* With TRANSLIT enabled: EILSEQ; output now truncated at the first invalid
UTF-8 character. */
test_iconv ("ASCII//TRANSLIT", "UTF-8", jutf8, strlen (jutf8) - 5,
(size_t) -1, ju2a_translit, EILSEQ);
test_iconv ("ASCII//translit", "UTF-8", jutf8, strlen (jutf8) - 5,
(size_t) -1, ju2a_translit, EILSEQ);
/* With IGNORE enabled: EILSEQ; output omits invalid UTF-8 characters and
valid UTF-8 non-ASCII characters. */
test_iconv ("ASCII//IGNORE", "UTF-8", jutf8, strlen (jutf8), (size_t) -1,
ju2a_ignore, EILSEQ);
test_iconv ("ASCII//ignore", "UTF-8", jutf8, strlen (jutf8), (size_t) -1,
ju2a_ignore, EILSEQ);
/* With TRANSLIT and IGNORE enabled, output omits only invalid UTF-8
characters and transliterates valid non-ASCII UTF-8 characters. We test
several combinations. */
test_iconv ("ASCII//TRANSLIT,IGNORE", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
/* Due to bug 19519, iconv was ignoring IGNORE for the following input. */
test_iconv ("ASCII//TRANSLIT//IGNORE", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
/* Due to bug 19519, iconv was ignoring TRANSLIT for the following input. */
test_iconv ("ASCII//IGNORE//TRANSLIT", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//translit,ignore", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
/* Trailing whitespace and separators should be ignored. */
test_iconv ("ASCII//IGNORE,TRANSLIT ", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT/", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT//", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT,", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT,,", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
test_iconv ("ASCII//IGNORE,TRANSLIT /,", "UTF-8", jutf8, strlen (jutf8), 2,
ju2a_both, 0);
/* TRANSLIT or IGNORE suffixes in fromcode should be ignored. */
test_iconv ("ASCII", "UTF-8//TRANSLIT", jutf8, strlen (ju2a), (size_t) -1,
ju2a, EILSEQ);
test_iconv ("ASCII", "UTF-8//IGNORE", jutf8, strlen (ju2a), (size_t) -1,
ju2a, EILSEQ);
test_iconv ("ASCII", "UTF-8//TRANSLIT,IGNORE", jutf8, strlen (ju2a),
(size_t) -1, ju2a, EILSEQ);
/* 5. Charset names of the form "A/B/": */
/* ISO-8859-1 is converted to UTF-8 without needing transliteration. */
test_iconv ("ISO-10646/UTF-8", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8/", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8/IGNORE", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8//IGNORE", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8//TRANSLIT", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8//TRANSLIT/IGNORE", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ISO-8859-1", iso8859_1_a,
strlen (iso8859_1_a), 0, utf8_a, 0);
/* UTF-8 with accented A's is converted to ASCII with transliteration. */
test_iconv ("ASCII", "ISO-10646/UTF-8", utf8_a,
0, (size_t) -1, empty, EILSEQ);
test_iconv ("ASCII//IGNORE", "ISO-10646/UTF-8", utf8_a,
strlen (utf8_a), (size_t) -1, empty, EILSEQ);
test_iconv ("ASCII//TRANSLIT", "ISO-10646/UTF-8", utf8_a,
strlen (utf8_a), 12, ascii_a, 0);
/* Invalid ASCII is converted to UTF-8 only with IGNORE. */
test_iconv ("ISO-10646/UTF-8", "ASCII", iascii, strlen (empty), (size_t) -1,
empty, EILSEQ);
test_iconv ("ISO-10646/UTF-8/TRANSLIT", "ASCII", iascii, strlen (empty),
(size_t) -1, empty, EILSEQ);
test_iconv ("ISO-10646/UTF-8/IGNORE", "ASCII", iascii, strlen (iascii),
(size_t) -1, ia2u_ignore, EILSEQ);
test_iconv ("ISO-10646/UTF-8/TRANSLIT,IGNORE", "ASCII", iascii,
strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ);
/* Due to bug 19519, iconv was ignoring IGNORE for the following three
inputs: */
test_iconv ("ISO-10646/UTF-8/TRANSLIT/IGNORE", "ASCII", iascii,
strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ);
test_iconv ("ISO-10646/UTF-8//TRANSLIT,IGNORE", "ASCII", iascii,
strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ);
test_iconv ("ISO-10646/UTF-8//TRANSLIT//IGNORE", "ASCII", iascii,
strlen (iascii), (size_t) -1, ia2u_ignore, EILSEQ);
return 0;
}
#include <support/test-driver.c>
+55
View File
@@ -0,0 +1,55 @@
/* Test iconv buffer handling with the IGNORE error handler.
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Derived from BZ #18830 */
#include <errno.h>
#include <iconv.h>
#include <stdio.h>
#include <support/check.h>
static int
do_test (void)
{
/* This conversion needs two steps, from ASCII to INTERNAL to ASCII. */
iconv_t cd = iconv_open ("ASCII//IGNORE", "ASCII");
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
/* Convert some irreversible sequence, enough to trigger an overflow of
the output buffer before the irreversible character in the second
step, but after going past the irreversible character in the first
step. */
char input[4 + 4] = { '0', '1', '2', '3', '4', '5', '\266', '7' };
char *inptr = input;
size_t insize = sizeof (input);
char output[4];
char *outptr = output;
size_t outsize = sizeof (output);
/* The conversion should fail. */
TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == (size_t) -1);
TEST_VERIFY (errno == E2BIG);
/* The conversion should not consume more than it was able to store in
the output buffer. */
TEST_COMPARE (inptr - input, sizeof (output) - outsize);
TEST_VERIFY_EXIT (iconv_close (cd) != -1);
return 0;
}
#include <support/test-driver.c>
+50
View File
@@ -0,0 +1,50 @@
/* Test iconv behavior on UCS4 conversions with //IGNORE.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Derived from BZ #26923 */
#include <errno.h>
#include <iconv.h>
#include <stdio.h>
#include <support/check.h>
static int
do_test (void)
{
iconv_t cd = iconv_open ("UTF-8//IGNORE", "ISO-10646/UCS4/");
TEST_VERIFY_EXIT (cd != (iconv_t) -1);
/*
* Convert sequence beginning with an irreversible character into buffer that
* is too small.
*/
char input[12] = "\xe1\x80\xa1" "AAAAAAAAA";
char *inptr = input;
size_t insize = sizeof (input);
char output[6];
char *outptr = output;
size_t outsize = sizeof (output);
TEST_VERIFY (iconv (cd, &inptr, &insize, &outptr, &outsize) == -1);
TEST_VERIFY (errno == E2BIG);
TEST_VERIFY_EXIT (iconv_close (cd) != -1);
return 0;
}
#include <support/test-driver.c>
+284
View File
@@ -0,0 +1,284 @@
#!/bin/bash
# Test for some known iconv(1) hangs from bug 19519, and miscellaneous
# iconv(1) program error conditions.
# Copyright (C) 2020 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# The GNU C Library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with the GNU C Library; if not, see
# <https://www.gnu.org/licenses/>.
codir=$1
test_wrapper_env="$2"
run_program_env="$3"
# We have to have some directories in the library path.
LIBPATH=$codir:$codir/iconvdata
# How the start the iconv(1) program. $from is not defined/expanded yet.
ICONV='
$codir/elf/ld.so --library-path $LIBPATH --inhibit-rpath ${from}.so
$codir/iconv/iconv_prog
'
ICONV="$test_wrapper_env $run_program_env $ICONV"
# List of known hangs;
# Gathered by running an exhaustive 2 byte input search against glibc-2.28
hangarray=(
"\x00\x23;-c;ANSI_X3.110;UTF-8//TRANSLIT//IGNORE"
"\x00\xa1;-c;ARMSCII-8;UTF-8//TRANSLIT//IGNORE"
"\x00\xa1;-c;ASMO_449;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;BIG5;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BIG5HKSCS;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BRF;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;BS_4730;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1250;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;CP1251;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1252;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1253;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1254;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1255;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1257;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;CP1258;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CP932;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CSA_Z243.4-1985-1;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;CSA_Z243.4-1985-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DEC-MCS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DIN_66003;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;DS_2089;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-AT-DE;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-AT-DE-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-CA-FR;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-DK-NO;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-DK-NO-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-ES-S;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FI-SE;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FI-SE-A;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-FR;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-IS-FRISS;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-IT;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-PT;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-UK;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;EBCDIC-US;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ES;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ES2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-CN;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JISX0213;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JP;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-JP-MS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-KR;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;EUC-TW;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GB18030;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GB_1988-80;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GBK;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GOST_19768-74;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK7;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK7-OLD;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;GREEK-CCITT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-GREEK8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-ROMAN8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-ROMAN9;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-THAI8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;HP-TURKISH8;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM038;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM1004;UTF-8//TRANSLIT//IGNORE"
"\x00\xff;-c;IBM1008;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM1046;UTF-8//TRANSLIT//IGNORE"
"\x00\x51;-c;IBM1132;UTF-8//TRANSLIT//IGNORE"
"\x00\xa0;-c;IBM1133;UTF-8//TRANSLIT//IGNORE"
"\x00\xce;-c;IBM1137;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM1161;UTF-8//TRANSLIT//IGNORE"
"\x00\xdb;-c;IBM1162;UTF-8//TRANSLIT//IGNORE"
"\x00\x70;-c;IBM12712;UTF-8//TRANSLIT//IGNORE"
"\x00\x0f;-c;IBM1364;UTF-8"
"\x0e\x0e;-c;IBM1364;UTF-8"
"\x00\x0f;-c;IBM1371;UTF-8"
"\x0e\x0e;-c;IBM1371;UTF-8"
"\x00\x0f;-c;IBM1388;UTF-8"
"\x0e\x0e;-c;IBM1388;UTF-8"
"\x00\x0f;-c;IBM1390;UTF-8"
"\x0e\x0e;-c;IBM1390;UTF-8"
"\x00\x0f;-c;IBM1399;UTF-8"
"\x0e\x0e;-c;IBM1399;UTF-8"
"\x00\x53;-c;IBM16804;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM274;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM275;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM281;UTF-8//TRANSLIT//IGNORE"
"\x00\x57;-c;IBM290;UTF-8//TRANSLIT//IGNORE"
"\x00\x45;-c;IBM420;UTF-8//TRANSLIT//IGNORE"
"\x00\x68;-c;IBM423;UTF-8//TRANSLIT//IGNORE"
"\x00\x70;-c;IBM424;UTF-8//TRANSLIT//IGNORE"
"\x00\x53;-c;IBM4517;UTF-8//TRANSLIT//IGNORE"
"\x00\x53;-c;IBM4899;UTF-8//TRANSLIT//IGNORE"
"\x00\xa5;-c;IBM4909;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;IBM4971;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM803;UTF-8//TRANSLIT//IGNORE"
"\x00\x91;-c;IBM851;UTF-8//TRANSLIT//IGNORE"
"\x00\x9b;-c;IBM856;UTF-8//TRANSLIT//IGNORE"
"\x00\xd5;-c;IBM857;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM864;UTF-8//TRANSLIT//IGNORE"
"\x00\x94;-c;IBM868;UTF-8//TRANSLIT//IGNORE"
"\x00\x94;-c;IBM869;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM874;UTF-8//TRANSLIT//IGNORE"
"\x00\x6a;-c;IBM875;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM880;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM891;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM903;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;IBM904;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM905;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM9066;UTF-8//TRANSLIT//IGNORE"
"\x00\x48;-c;IBM918;UTF-8//TRANSLIT//IGNORE"
"\x00\x57;-c;IBM930;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM932;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM933;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM935;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM937;UTF-8//TRANSLIT//IGNORE"
"\x00\x41;-c;IBM939;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IBM943;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS-8;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;INIS-CYRILLIC;UTF-8//TRANSLIT//IGNORE"
"\x00\xec;-c;ISIRI-3342;UTF-8//TRANSLIT//IGNORE"
"\x00\xec;-c;ISO_10367-BOX;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-CN;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-CN-EXT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-JP-3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-2022-KR;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_2033;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5427;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5427-EXT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO_5428;UTF-8//TRANSLIT//IGNORE"
"\x00\xa4;-c;ISO_6937;UTF-8//TRANSLIT//IGNORE"
"\x00\xa0;-c;ISO_6937-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-11;UTF-8//TRANSLIT//IGNORE"
"\x00\xa5;-c;ISO-8859-3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-6;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-7;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;ISO-8859-8;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;ISO-IR-197;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;ISO-IR-209;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;IT;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JIS_C6220-1969-RO;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JIS_C6229-1984-B;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JOHAB;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;JUS_I.B1.002;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;KOI-8;UTF-8//TRANSLIT//IGNORE"
"\x00\x88;-c;KOI8-T;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;KSC5636;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;LATIN-GREEK;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;LATIN-GREEK-1;UTF-8//TRANSLIT//IGNORE"
"\x00\xf6;-c;MAC-IS;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;MSZ_7795.3;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NATS-DANO;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NATS-SEFI;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NC_NC00-10;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NF_Z_62-010;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NF_Z_62-010_1973;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NS_4551-1;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;NS_4551-2;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;PT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;PT2;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;RK1048;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;SEN_850200_B;UTF-8//TRANSLIT//IGNORE"
"\x00\x98;-c;SEN_850200_C;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;Shift_JISX0213;UTF-8//TRANSLIT//IGNORE"
"\x00\x80;-c;SJIS;UTF-8//TRANSLIT//IGNORE"
"\x00\x23;-c;T.61-8BIT;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;TIS-620;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;TSCII;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;UHC;UTF-8//TRANSLIT//IGNORE"
"\x00\xd8;-c;UNICODE;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;UTF-16;UTF-8//TRANSLIT//IGNORE"
"\xdc\x00;-c;UTF-16BE;UTF-8//TRANSLIT//IGNORE"
"\x00\xdc;-c;UTF-16LE;UTF-8//TRANSLIT//IGNORE"
"\xff\xff;-c;UTF-7;UTF-8//TRANSLIT//IGNORE"
"\x00\x81;-c;WIN-SAMI-2;UTF-8//TRANSLIT//IGNORE"
)
# List of option combinations that *should* lead to an error
errorarray=(
# Converting from/to invalid character sets should cause error
"\x00\x00;;INVALID;INVALID"
"\x00\x00;;INVALID;UTF-8"
"\x00\x00;;UTF-8;INVALID"
)
# Requires $twobyte input, $c flag, $from, and $to to be set; sets $ret
execute_test ()
{
eval PROG=\"$ICONV\"
echo -en "$twobyte" \
| timeout -k 4 3 $PROG $c -f $from -t "$to" &>/dev/null
ret=$?
}
check_hangtest_result ()
{
if [ "$ret" -eq "124" ] || [ "$ret" -eq "137" ]; then # timeout/hang
result="HANG"
else
if [ "$ret" -eq "139" ]; then # segfault
result="SEGFAULT"
else
if [ "$ret" -gt "127" ]; then # unexpected error
result="UNEXPECTED"
else
result="OK"
fi
fi
fi
echo -n "$result: from: \"$from\", to: \"$to\","
echo " input \"$twobyte\", flags \"$c\""
if [ "$result" != "OK" ]; then
exit 1
fi
}
for hangcommand in "${hangarray[@]}"; do
twobyte="$(echo "$hangcommand" | cut -d";" -f 1)"
c="$(echo "$hangcommand" | cut -d";" -f 2)"
from="$(echo "$hangcommand" | cut -d";" -f 3)"
to="$(echo "$hangcommand" | cut -d";" -f 4)"
execute_test
check_hangtest_result
done
check_errtest_result ()
{
if [ "$ret" -eq "1" ]; then # we errored out as expected
result="PASS"
else
result="FAIL"
fi
echo -n "$result: from: \"$from\", to: \"$to\","
echo " input \"$twobyte\", flags \"$c\", return code $ret"
if [ "$result" != "PASS" ]; then
exit 1
fi
}
for errorcommand in "${errorarray[@]}"; do
twobyte="$(echo "$errorcommand" | cut -d";" -f 1)"
c="$(echo "$errorcommand" | cut -d";" -f 2)"
from="$(echo "$errorcommand" | cut -d";" -f 3)"
to="$(echo "$errorcommand" | cut -d";" -f 4)"
execute_test
check_errtest_result
done
+2 -12
View File
@@ -157,24 +157,14 @@ enum
\
if (__builtin_expect (ch, 0) == SO) \
{ \
/* Shift OUT, change to DBCS converter. */ \
if (curcs == db) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
/* Shift OUT, change to DBCS converter (redundant escape okay). */ \
curcs = db; \
++inptr; \
continue; \
} \
if (__builtin_expect (ch, 0) == SI) \
{ \
/* Shift IN, change to SBCS converter. */ \
if (curcs == sb) \
{ \
result = __GCONV_ILLEGAL_INPUT; \
break; \
} \
/* Shift IN, change to SBCS converter (redundant escape okay). */ \
curcs = sb; \
++inptr; \
continue; \
+4
View File
@@ -216,6 +216,10 @@ struct link_map
unsigned int boundndx;
uint32_t enterexit;
unsigned int flags;
/* CONCURRENCY NOTE: This is used to guard the concurrent initialization
of the relocation result across multiple threads. See the more
detailed notes in elf/dl-runtime.c. */
unsigned int init;
} *l_reloc_result;
/* Pointer to the version information if available. */
+1
View File
@@ -28,6 +28,7 @@ libc_hidden_proto (clntudp_create)
libc_hidden_proto (get_myaddress)
libc_hidden_proto (clntunix_create)
libc_hidden_proto (__libc_clntudp_bufcreate)
libc_hidden_proto (rpc_createerr)
# endif /* !_ISOMAC */
#endif
+4
View File
@@ -3,6 +3,10 @@
# ifndef _ISOMAC
libc_hidden_proto (svc_pollfd)
libc_hidden_proto (svc_max_pollfd)
libc_hidden_proto (svc_fdset)
libc_hidden_proto (xprt_register)
libc_hidden_proto (xprt_unregister)
libc_hidden_proto (svc_register)
+2
View File
@@ -77,6 +77,8 @@ extern char *__getcwd (char *__buf, size_t __size) attribute_hidden;
extern int __rmdir (const char *__path) attribute_hidden;
extern int __execvpe (const char *file, char *const argv[],
char *const envp[]) attribute_hidden;
extern int __execvpex (const char *file, char *const argv[],
char *const envp[]) attribute_hidden;
/* Get the canonical absolute name of the named directory, and put it in SIZE
bytes of BUF. Returns NULL if the directory couldn't be determined or
+1 -1
View File
@@ -52,7 +52,7 @@ aux := check_pf check_native ifreq
tests := htontest test_ifindex tst-ntoa tst-ether_aton tst-network \
tst-gethnm test-ifaddrs bug-if1 test-inet6_opt tst-ether_line \
tst-getni1 tst-getni2 tst-inet6_rth tst-checks tst-checks-posix \
tst-sockaddr test-hnto-types
tst-sockaddr test-hnto-types tst-if_index-long
# tst-deadline must be linked statically so that we can access
# internal functions.
+61
View File
@@ -0,0 +1,61 @@
/* Check for descriptor leak in if_nametoindex with a long interface name.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test checks for a descriptor leak in case of a long interface
name (CVE-2018-19591, bug 23927). */
#include <errno.h>
#include <net/if.h>
#include <netdb.h>
#include <string.h>
#include <support/check.h>
#include <support/descriptors.h>
#include <support/support.h>
static int
do_test (void)
{
struct support_descriptors *descrs = support_descriptors_list ();
/* Prepare a name which is just as long as required for trigging the
bug. */
char name[IFNAMSIZ + 1];
memset (name, 'A', IFNAMSIZ);
name[IFNAMSIZ] = '\0';
TEST_COMPARE (strlen (name), IFNAMSIZ);
struct ifreq ifr;
TEST_COMPARE (strlen (name), sizeof (ifr.ifr_name));
/* Test directly via if_nametoindex. */
TEST_COMPARE (if_nametoindex (name), 0);
TEST_COMPARE (errno, ENODEV);
support_descriptors_check (descrs);
/* Same test via getaddrinfo. */
char *host = xasprintf ("fea0::%%%s", name);
struct addrinfo hints = { .ai_flags = AI_NUMERICHOST, };
struct addrinfo *ai;
TEST_COMPARE (getaddrinfo (host, NULL, &hints, &ai), EAI_NONAME);
support_descriptors_check (descrs);
support_descriptors_free (descrs);
return 0;
}
#include <support/test-driver.c>
+5 -1
View File
@@ -120,7 +120,11 @@ $(objpfx)tst-gettext6.out: $(gen-locales)
$(objpfx)tst-translit.out: $(gen-locales)
endif
$(objpfx)msgs.h: po2test.awk ../po/de.po
$(objpfx)tst-gettext-de.po: ../po/de.po
$(make-target-directory)
LC_ALL=C $(AWK) '!/^"POT-Creation-Date: [0-9-]+ [0-9:+-]+\\n"$$/' $^ > $@
$(objpfx)msgs.h: po2test.awk $(objpfx)tst-gettext-de.po
$(make-target-directory)
LC_ALL=C $(AWK) -f $^ > $@
+13 -5
View File
@@ -631,7 +631,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname);
free (cwd);
if (ret < 0)
return NULL;
goto return_untranslated;
dirname = xdirname;
}
#ifndef IN_LIBGLOCALE
@@ -1120,11 +1120,19 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
outcharset = encoding;
# ifdef _LIBC
struct gconv_spec conv_spec;
__gconv_create_spec (&conv_spec, charset, outcharset);
/* We always want to use transliteration. */
outcharset = norm_add_slashes (outcharset, "TRANSLIT");
charset = norm_add_slashes (charset, "");
int r = __gconv_open (outcharset, charset, &convd->conv,
GCONV_AVOID_NOCONV);
conv_spec.translit = true;
int r = __gconv_open (&conv_spec, &convd->conv,
GCONV_AVOID_NOCONV);
__gconv_destroy_spec (&conv_spec);
if (__builtin_expect (r != __GCONV_OK, 0))
{
/* If the output encoding is the same there is
+14 -20
View File
@@ -22,13 +22,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
static int
do_test (void)
{
char *s;
int result = 0;
unsetenv ("LANGUAGE");
unsetenv ("OUTPUT_CHARSET");
setlocale (LC_ALL, "de_DE.ISO-8859-1");
@@ -36,25 +34,21 @@ do_test (void)
bindtextdomain ("codeset", OBJPFX "domaindir");
/* Here we expect output in ISO-8859-1. */
s = gettext ("cheese");
if (strcmp (s, "K\344se"))
{
printf ("call 1 returned: %s\n", s);
result = 1;
}
bind_textdomain_codeset ("codeset", "UTF-8");
TEST_COMPARE_STRING (gettext ("cheese"), "K\344se");
/* Here we expect output in UTF-8. */
s = gettext ("cheese");
if (strcmp (s, "K\303\244se"))
{
printf ("call 2 returned: %s\n", s);
result = 1;
}
bind_textdomain_codeset ("codeset", "UTF-8");
TEST_COMPARE_STRING (gettext ("cheese"), "K\303\244se");
return result;
/* `a with umlaut' is transliterated to `ae'. */
bind_textdomain_codeset ("codeset", "ASCII//TRANSLIT");
TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
/* Transliteration also works by default even if not set. */
bind_textdomain_codeset ("codeset", "ASCII");
TEST_COMPARE_STRING (gettext ("cheese"), "Kaese");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
#include <support/test-driver.c>
+2 -2
View File
@@ -42,9 +42,9 @@ mkdir -p ${objpfx}domaindir/existing-locale/LC_MESSAGES
mkdir -p ${objpfx}domaindir/existing-locale/LC_TIME
# Populate them.
msgfmt -o ${objpfx}domaindir/existing-locale/LC_MESSAGES/existing-domain.mo \
-f ../po/de.po
-f ${objpfx}tst-gettext-de.po
msgfmt -o ${objpfx}domaindir/existing-locale/LC_TIME/existing-time-domain.mo \
-f ../po/de.po
-f ${objpfx}tst-gettext-de.po
# Now run the test.
${test_program_prefix_before_env} \
-5
View File
@@ -73,11 +73,6 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
tst-fts tst-fts-lfs tst-open-tmpfile \
tst-copy_file_range tst-getcwd-abspath \
# This test includes the compat implementation of copy_file_range,
# which uses internal, unexported libc functions.
tests-static += tst-copy_file_range-compat
tests-internal += tst-copy_file_range-compat
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)ftwtest.out
endif
-160
View File
@@ -1,160 +0,0 @@
/* Emulation of copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* The following macros should be defined before including this
file:
COPY_FILE_RANGE_DECL Declaration specifiers for the function below.
COPY_FILE_RANGE Name of the function to define. */
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
COPY_FILE_RANGE_DECL
ssize_t
COPY_FILE_RANGE (int infd, __off64_t *pinoff,
int outfd, __off64_t *poutoff,
size_t length, unsigned int flags)
{
if (flags != 0)
{
__set_errno (EINVAL);
return -1;
}
{
struct stat64 instat;
struct stat64 outstat;
if (fstat64 (infd, &instat) != 0 || fstat64 (outfd, &outstat) != 0)
return -1;
if (S_ISDIR (instat.st_mode) || S_ISDIR (outstat.st_mode))
{
__set_errno (EISDIR);
return -1;
}
if (!S_ISREG (instat.st_mode) || !S_ISREG (outstat.st_mode))
{
/* We need a regular input file so that the we can seek
backwards in case of a write failure. */
__set_errno (EINVAL);
return -1;
}
if (instat.st_dev != outstat.st_dev)
{
/* Cross-device copies are not supported. */
__set_errno (EXDEV);
return -1;
}
}
/* The output descriptor must not have O_APPEND set. */
{
int flags = __fcntl (outfd, F_GETFL);
if (flags & O_APPEND)
{
__set_errno (EBADF);
return -1;
}
}
/* Avoid an overflow in the result. */
if (length > SSIZE_MAX)
length = SSIZE_MAX;
/* Main copying loop. The buffer size is arbitrary and is a
trade-off between stack size consumption, cache usage, and
amortization of system call overhead. */
size_t copied = 0;
char buf[8192];
while (length > 0)
{
size_t to_read = length;
if (to_read > sizeof (buf))
to_read = sizeof (buf);
/* Fill the buffer. */
ssize_t read_count;
if (pinoff == NULL)
read_count = read (infd, buf, to_read);
else
read_count = __libc_pread64 (infd, buf, to_read, *pinoff);
if (read_count == 0)
/* End of file reached prematurely. */
return copied;
if (read_count < 0)
{
if (copied > 0)
/* Report the number of bytes copied so far. */
return copied;
return -1;
}
if (pinoff != NULL)
*pinoff += read_count;
/* Write the buffer part which was read to the destination. */
char *end = buf + read_count;
for (char *p = buf; p < end; )
{
ssize_t write_count;
if (poutoff == NULL)
write_count = write (outfd, p, end - p);
else
write_count = __libc_pwrite64 (outfd, p, end - p, *poutoff);
if (write_count < 0)
{
/* Adjust the input read position to match what we have
written, so that the caller can pick up after the
error. */
size_t written = p - buf;
/* NB: This needs to be signed so that we can form the
negative value below. */
ssize_t overread = read_count - written;
if (pinoff == NULL)
{
if (overread > 0)
{
/* We are on an error recovery path, so we
cannot deal with failure here. */
int save_errno = errno;
(void) __libc_lseek64 (infd, -overread, SEEK_CUR);
__set_errno (save_errno);
}
}
else /* pinoff != NULL */
*pinoff -= overread;
if (copied + written > 0)
/* Report the number of bytes copied so far. */
return copied + written;
return -1;
}
p += write_count;
if (poutoff != NULL)
*poutoff += write_count;
} /* Write loop. */
copied += read_count;
length -= read_count;
}
return copied;
}
+13 -5
View File
@@ -1,5 +1,5 @@
/* Generic implementation of copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
/* Stub implementation of copy_file_range.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -16,7 +16,15 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#define COPY_FILE_RANGE_DECL
#define COPY_FILE_RANGE copy_file_range
#include <errno.h>
#include <unistd.h>
#include <io/copy_file_range-compat.c>
ssize_t
copy_file_range (int infd, __off64_t *pinoff,
int outfd, __off64_t *poutoff,
size_t length, unsigned int flags)
{
__set_errno (ENOSYS);
return -1;
}
stub_warning (copy_file_range)
+1 -1
View File
@@ -139,7 +139,7 @@ typedef __pid_t pid_t;
# define SEEK_END 2 /* Seek from end of file. */
#endif /* XPG */
/* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EASSESS
/* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS
is meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
unlinkat. The two functions do completely different things and therefore,
the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
+10 -547
View File
@@ -1,5 +1,5 @@
/* Tests for copy_file_range.
Copyright (C) 2017-2018 Free Software Foundation, Inc.
Copyright (C) 2017-2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -20,22 +20,15 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libgen.h>
#include <poll.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
#include <support/temp_file.h>
#include <support/test-driver.h>
#include <support/xunistd.h>
#ifdef CLONE_NEWNS
# include <sys/mount.h>
#endif
/* Boolean flags which indicate whether to use pointers with explicit
output flags. */
@@ -49,10 +42,6 @@ static int infd;
static char *outfile;
static int outfd;
/* Like the above, but on a different file system. xdevfile can be
NULL if no suitable file system has been found. */
static char *xdevfile;
/* Input and output offsets. Set according to do_inoff and do_outoff
before the test. The offsets themselves are always set to
zero. */
@@ -61,13 +50,10 @@ static off64_t *pinoff;
static off64_t outoff;
static off64_t *poutoff;
/* These are a collection of copy sizes used in tests. The selection
takes into account that the fallback implementation uses an
internal buffer of 8192 bytes. */
/* These are a collection of copy sizes used in tests. */
enum { maximum_size = 99999 };
static const int typical_sizes[] =
{ 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, 16383, 16384, 16385,
maximum_size };
{ 0, 1, 2, 3, 1024, 2048, 4096, 8191, 8192, 8193, maximum_size };
/* The random contents of this array can be used as a pattern to check
for correct write operations. */
@@ -76,101 +62,6 @@ static unsigned char random_data[maximum_size];
/* The size chosen by the test harness. */
static int current_size;
/* Maximum writable file offset. Updated by find_maximum_offset
below. */
static off64_t maximum_offset;
/* Error code when crossing the offset. */
static int maximum_offset_errno;
/* If true: Writes which cross the limit will fail. If false: Writes
which cross the limit will result in a partial write. */
static bool maximum_offset_hard_limit;
/* Fills maximum_offset etc. above. Truncates outfd as a side
effect. */
static void
find_maximum_offset (void)
{
xftruncate (outfd, 0);
if (maximum_offset != 0)
return;
uint64_t upper = -1;
upper >>= 1; /* Maximum of off64_t. */
TEST_VERIFY ((off64_t) upper > 0);
TEST_VERIFY ((off64_t) (upper + 1) < 0);
if (lseek64 (outfd, upper, SEEK_SET) >= 0)
{
if (write (outfd, "", 1) == 1)
FAIL_EXIT1 ("created a file larger than the off64_t range");
}
uint64_t lower = 1024 * 1024; /* A reasonable minimum file size. */
/* Loop invariant: writing at lower succeeds, writing at upper fails. */
while (lower + 1 < upper)
{
uint64_t middle = (lower + upper) / 2;
if (test_verbose > 0)
printf ("info: %s: remaining test range %" PRIu64 " .. %" PRIu64
", probe at %" PRIu64 "\n", __func__, lower, upper, middle);
xftruncate (outfd, 0);
if (lseek64 (outfd, middle, SEEK_SET) >= 0
&& write (outfd, "", 1) == 1)
lower = middle;
else
upper = middle;
}
TEST_VERIFY (lower + 1 == upper);
maximum_offset = lower;
printf ("info: maximum writable file offset: %" PRIu64 " (%" PRIx64 ")\n",
lower, lower);
/* Check that writing at the valid offset actually works. */
xftruncate (outfd, 0);
xlseek (outfd, lower, SEEK_SET);
TEST_COMPARE (write (outfd, "", 1), 1);
/* Cross the boundary with a two-byte write. This can either result
in a short write, or a failure. */
xlseek (outfd, lower, SEEK_SET);
ssize_t ret = write (outfd, " ", 2);
if (ret < 0)
{
maximum_offset_errno = errno;
maximum_offset_hard_limit = true;
}
else
maximum_offset_hard_limit = false;
/* Check that writing at the next offset actually fails. This also
obtains the expected errno value. */
xftruncate (outfd, 0);
const char *action;
if (lseek64 (outfd, lower + 1, SEEK_SET) != 0)
{
if (write (outfd, "", 1) != -1)
FAIL_EXIT1 ("write to impossible offset %" PRIu64 " succeeded",
lower + 1);
action = "writing";
int errno_copy = errno;
if (maximum_offset_hard_limit)
TEST_COMPARE (errno_copy, maximum_offset_errno);
else
maximum_offset_errno = errno_copy;
}
else
{
action = "seeking";
maximum_offset_errno = errno;
}
printf ("info: %s out of range fails with %m (%d)\n",
action, maximum_offset_errno);
xftruncate (outfd, 0);
xlseek (outfd, 0, SEEK_SET);
}
/* Perform a copy of a file. */
static void
simple_file_copy (void)
@@ -247,390 +138,6 @@ simple_file_copy (void)
free (bytes);
}
/* Test that reading from a pipe willfails. */
static void
pipe_as_source (void)
{
int pipefds[2];
xpipe (pipefds);
for (int length = 0; length < 2; ++length)
{
if (test_verbose > 0)
printf ("info: %s: length=%d\n", __func__, length);
/* Make sure that there is something to copy in the pipe. */
xwrite (pipefds[1], "@", 1);
TEST_COMPARE (copy_file_range (pipefds[0], pinoff, outfd, poutoff,
length, 0), -1);
/* Linux 4.10 and later return EINVAL. Older kernels return
EXDEV. */
TEST_VERIFY (errno == EINVAL || errno == EXDEV);
TEST_COMPARE (inoff, 0);
TEST_COMPARE (outoff, 0);
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 0);
/* Make sure that nothing was read. */
char buf = 'A';
TEST_COMPARE (read (pipefds[0], &buf, 1), 1);
TEST_COMPARE (buf, '@');
}
xclose (pipefds[0]);
xclose (pipefds[1]);
}
/* Test that writing to a pipe fails. */
static void
pipe_as_destination (void)
{
/* Make sure that there is something to read in the input file. */
xwrite (infd, "abc", 3);
xlseek (infd, 0, SEEK_SET);
int pipefds[2];
xpipe (pipefds);
for (int length = 0; length < 2; ++length)
{
if (test_verbose > 0)
printf ("info: %s: length=%d\n", __func__, length);
TEST_COMPARE (copy_file_range (infd, pinoff, pipefds[1], poutoff,
length, 0), -1);
/* Linux 4.10 and later return EINVAL. Older kernels return
EXDEV. */
TEST_VERIFY (errno == EINVAL || errno == EXDEV);
TEST_COMPARE (inoff, 0);
TEST_COMPARE (outoff, 0);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
/* Make sure that nothing was written. */
struct pollfd pollfd = { .fd = pipefds[0], .events = POLLIN, };
TEST_COMPARE (poll (&pollfd, 1, 0), 0);
}
xclose (pipefds[0]);
xclose (pipefds[1]);
}
/* Test a write failure after (potentially) writing some bytes.
Failure occurs near the start of the buffer. */
static void
delayed_write_failure_beginning (void)
{
/* We need to write something to provoke the error. */
if (current_size == 0)
return;
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
/* Write failure near the start. The actual error code varies among
file systems. */
find_maximum_offset ();
off64_t where = maximum_offset;
if (current_size == 1)
++where;
outoff = where;
if (do_outoff)
xlseek (outfd, 1, SEEK_SET);
else
xlseek (outfd, where, SEEK_SET);
if (maximum_offset_hard_limit || where > maximum_offset)
{
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), -1);
TEST_COMPARE (errno, maximum_offset_errno);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
TEST_COMPARE (inoff, 0);
if (do_outoff)
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1);
else
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where);
TEST_COMPARE (outoff, where);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, 0);
}
else
{
/* The offset is not a hard limit. This means we write one
byte. */
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), 1);
if (do_inoff)
{
TEST_COMPARE (inoff, 1);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
}
else
{
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 1);
TEST_COMPARE (inoff, 0);
}
if (do_outoff)
{
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), 1);
TEST_COMPARE (outoff, where + 1);
}
else
{
TEST_COMPARE (xlseek (outfd, 0, SEEK_CUR), where + 1);
TEST_COMPARE (outoff, where);
}
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, where + 1);
}
}
/* Test a write failure after (potentially) writing some bytes.
Failure occurs near the end of the buffer. */
static void
delayed_write_failure_end (void)
{
if (current_size <= 1)
/* This would be same as the first test because there is not
enough data to write to make a difference. */
return;
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
find_maximum_offset ();
off64_t where = maximum_offset - current_size + 1;
if (current_size == sizeof (random_data))
/* Otherwise we do not reach the non-writable byte. */
++where;
outoff = where;
if (do_outoff)
xlseek (outfd, 1, SEEK_SET);
else
xlseek (outfd, where, SEEK_SET);
ssize_t ret = copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0);
if (ret < 0)
{
TEST_COMPARE (ret, -1);
TEST_COMPARE (errno, maximum_offset_errno);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, 0);
}
else
{
/* The first copy succeeded. This happens in the emulation
because the internal buffer of limited size does not
necessarily cross the off64_t boundary on the first write
operation. */
if (test_verbose > 0)
printf ("info: copy_file_range (%zu) returned %zd\n",
sizeof (random_data), ret);
TEST_VERIFY (ret > 0);
TEST_VERIFY (ret < maximum_size);
struct stat64 st;
xfstat (outfd, &st);
TEST_COMPARE (st.st_size, where + ret);
if (do_inoff)
{
TEST_COMPARE (inoff, ret);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
}
else
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), ret);
char *buffer = xmalloc (ret);
TEST_COMPARE (pread64 (outfd, buffer, ret, where), ret);
TEST_VERIFY (memcmp (buffer, random_data, ret) == 0);
free (buffer);
/* The second copy fails. */
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
sizeof (random_data), 0), -1);
TEST_COMPARE (errno, maximum_offset_errno);
}
}
/* Test a write failure across devices. */
static void
cross_device_failure (void)
{
if (xdevfile == NULL)
/* Subtest not supported due to missing cross-device file. */
return;
/* We need something to write. */
xwrite (infd, random_data, sizeof (random_data));
xlseek (infd, 0, SEEK_SET);
int xdevfd = xopen (xdevfile, O_RDWR | O_LARGEFILE, 0);
TEST_COMPARE (copy_file_range (infd, pinoff, xdevfd, poutoff,
current_size, 0), -1);
TEST_COMPARE (errno, EXDEV);
TEST_COMPARE (xlseek (infd, 0, SEEK_CUR), 0);
struct stat64 st;
xfstat (xdevfd, &st);
TEST_COMPARE (st.st_size, 0);
xclose (xdevfd);
}
/* Try to exercise ENOSPC behavior with a tempfs file system (so that
we do not have to fill up a regular file system to get the error).
This function runs in a subprocess, so that we do not change the
mount namespace of the actual test process. */
static void
enospc_failure_1 (void *closure)
{
#ifdef CLONE_NEWNS
support_become_root ();
/* Make sure that we do not alter the file system mounts of the
parents. */
if (! support_enter_mount_namespace ())
{
printf ("warning: ENOSPC test skipped\n");
return;
}
char *mountpoint = closure;
if (mount ("none", mountpoint, "tmpfs", MS_NODEV | MS_NOEXEC,
"size=500k") != 0)
{
printf ("warning: could not mount tmpfs at %s: %m\n", mountpoint);
return;
}
/* The source file must reside on the same file system. */
char *intmpfsfile = xasprintf ("%s/%s", mountpoint, "in");
int intmpfsfd = xopen (intmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600);
xwrite (intmpfsfd, random_data, sizeof (random_data));
xlseek (intmpfsfd, 1, SEEK_SET);
inoff = 1;
char *outtmpfsfile = xasprintf ("%s/%s", mountpoint, "out");
int outtmpfsfd = xopen (outtmpfsfile, O_RDWR | O_CREAT | O_LARGEFILE, 0600);
/* Fill the file with data until ENOSPC is reached. */
while (true)
{
ssize_t ret = write (outtmpfsfd, random_data, sizeof (random_data));
if (ret < 0 && errno != ENOSPC)
FAIL_EXIT1 ("write to %s: %m", outtmpfsfile);
if (ret < sizeof (random_data))
break;
}
TEST_COMPARE (write (outtmpfsfd, "", 1), -1);
TEST_COMPARE (errno, ENOSPC);
off64_t maxsize = xlseek (outtmpfsfd, 0, SEEK_CUR);
TEST_VERIFY_EXIT (maxsize > sizeof (random_data));
/* Constructed the expected file contents. */
char *expected = xmalloc (maxsize);
TEST_COMPARE (pread64 (outtmpfsfd, expected, maxsize, 0), maxsize);
/* Go back a little, so some bytes can be written. */
enum { offset = 20000 };
TEST_VERIFY_EXIT (offset < maxsize);
TEST_VERIFY_EXIT (offset < sizeof (random_data));
memcpy (expected + maxsize - offset, random_data + 1, offset);
if (do_outoff)
{
outoff = maxsize - offset;
xlseek (outtmpfsfd, 2, SEEK_SET);
}
else
xlseek (outtmpfsfd, -offset, SEEK_CUR);
/* First call is expected to succeed because we made room for some
bytes. */
TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff,
maximum_size, 0), offset);
if (do_inoff)
{
TEST_COMPARE (inoff, 1 + offset);
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1);
}
else
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset);
if (do_outoff)
{
TEST_COMPARE (outoff, maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2);
}
else
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize);
struct stat64 st;
xfstat (outtmpfsfd, &st);
TEST_COMPARE (st.st_size, maxsize);
char *actual = xmalloc (st.st_size);
TEST_COMPARE (pread64 (outtmpfsfd, actual, st.st_size, 0), st.st_size);
TEST_VERIFY (memcmp (expected, actual, maxsize) == 0);
/* Second call should fail with ENOSPC. */
TEST_COMPARE (copy_file_range (intmpfsfd, pinoff, outtmpfsfd, poutoff,
maximum_size, 0), -1);
TEST_COMPARE (errno, ENOSPC);
/* Offsets should be unchanged. */
if (do_inoff)
{
TEST_COMPARE (inoff, 1 + offset);
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1);
}
else
TEST_COMPARE (xlseek (intmpfsfd, 0, SEEK_CUR), 1 + offset);
if (do_outoff)
{
TEST_COMPARE (outoff, maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), 2);
}
else
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_CUR), maxsize);
TEST_COMPARE (xlseek (outtmpfsfd, 0, SEEK_END), maxsize);
TEST_COMPARE (pread64 (outtmpfsfd, actual, maxsize, 0), maxsize);
TEST_VERIFY (memcmp (expected, actual, maxsize) == 0);
free (actual);
free (expected);
xclose (intmpfsfd);
xclose (outtmpfsfd);
free (intmpfsfile);
free (outtmpfsfile);
#else /* !CLONE_NEWNS */
puts ("warning: ENOSPC test skipped (no mount namespaces)");
#endif
}
/* Call enospc_failure_1 in a subprocess. */
static void
enospc_failure (void)
{
char *mountpoint
= support_create_temp_directory ("tst-copy_file_range-enospc-");
support_isolate_in_subprocess (enospc_failure_1, mountpoint);
free (mountpoint);
}
/* The target file descriptor must have O_APPEND enabled. */
static void
oappend_failure (void)
{
/* Add data, to make sure we do not fail because there is
insufficient input data. */
xwrite (infd, random_data, current_size);
xlseek (infd, 0, SEEK_SET);
xclose (outfd);
outfd = xopen (outfile, O_RDWR | O_APPEND, 0);
TEST_COMPARE (copy_file_range (infd, pinoff, outfd, poutoff,
current_size, 0), -1);
TEST_COMPARE (errno, EBADF);
}
/* Test that a short input file results in a shortened copy. */
static void
short_copy (void)
@@ -721,14 +228,6 @@ struct test_case
static struct test_case tests[] =
{
{ "simple_file_copy", simple_file_copy, .sizes = true },
{ "pipe_as_source", pipe_as_source, },
{ "pipe_as_destination", pipe_as_destination, },
{ "delayed_write_failure_beginning", delayed_write_failure_beginning,
.sizes = true },
{ "delayed_write_failure_end", delayed_write_failure_end, .sizes = true },
{ "cross_device_failure", cross_device_failure, .sizes = true },
{ "enospc_failure", enospc_failure, },
{ "oappend_failure", oappend_failure, .sizes = true },
{ "short_copy", short_copy, .sizes = true },
};
@@ -739,53 +238,18 @@ do_test (void)
*p = rand () >> 24;
infd = create_temp_file ("tst-copy_file_range-in-", &infile);
xclose (create_temp_file ("tst-copy_file_range-out-", &outfile));
/* Try to find a different directory from the default input/output
file. */
outfd = create_temp_file ("tst-copy_file_range-out-", &outfile);
{
struct stat64 instat;
xfstat (infd, &instat);
static const char *const candidates[] =
{ NULL, "/var/tmp", "/dev/shm" };
for (const char *const *c = candidates; c < array_end (candidates); ++c)
ssize_t ret = copy_file_range (infd, NULL, outfd, NULL, 0, 0);
if (ret != 0)
{
const char *path = *c;
char *to_free = NULL;
if (path == NULL)
{
to_free = xreadlink ("/proc/self/exe");
path = dirname (to_free);
}
struct stat64 cstat;
xstat (path, &cstat);
if (cstat.st_dev == instat.st_dev)
{
free (to_free);
continue;
}
printf ("info: using alternate temporary files directory: %s\n", path);
xdevfile = xasprintf ("%s/tst-copy_file_range-xdev-XXXXXX", path);
free (to_free);
break;
if (errno == ENOSYS)
FAIL_UNSUPPORTED ("copy_file_range is not support on this system");
FAIL_EXIT1 ("copy_file_range probing call: %m");
}
if (xdevfile != NULL)
{
int xdevfd = mkstemp (xdevfile);
if (xdevfd < 0)
FAIL_EXIT1 ("mkstemp (\"%s\"): %m", xdevfile);
struct stat64 xdevst;
xfstat (xdevfd, &xdevst);
TEST_VERIFY (xdevst.st_dev != instat.st_dev);
add_temp_file (xdevfile);
xclose (xdevfd);
}
else
puts ("warning: no alternate directory on different file system found");
}
xclose (infd);
xclose (outfd);
for (do_inoff = 0; do_inoff < 2; ++do_inoff)
for (do_outoff = 0; do_outoff < 2; ++do_outoff)
@@ -827,7 +291,6 @@ do_test (void)
free (infile);
free (outfile);
free (xdevfile);
return 0;
}
+18 -2
View File
@@ -63,11 +63,17 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
tst-ftell-append tst-fputws tst-bz22415
tst-ftell-append tst-fputws tst-bz22415 tst-wfile-sync
tests-internal = tst-vtables tst-vtables-interposed
ifeq (yes,$(build-shared))
# Add test-fopenloc only if shared library is enabled since it depends on
# shared localedata objects.
tests += tst-fopenloc
# Add tst-bz24228 only if shared library is enabled since it can never meet its
# objective with static linking because the relevant code just is not there.
tests += tst-bz24228
endif
test-srcs = test-freopen
@@ -148,11 +154,14 @@ CFLAGS-oldtmpfile.c += -fexceptions
CFLAGS-tst_putwc.c += -DOBJPFX=\"$(objpfx)\"
LDFLAGS-tst-bz24228 = -Wl,--version-script=tst-bz24228.map
tst_wprintf2-ARGS = "Some Text"
test-fmemopen-ENV = MALLOC_TRACE=$(objpfx)test-fmemopen.mtrace
tst-fopenloc-ENV = MALLOC_TRACE=$(objpfx)tst-fopenloc.mtrace
tst-bz22415-ENV = MALLOC_TRACE=$(objpfx)tst-bz22415.mtrace
tst-bz24228-ENV = MALLOC_TRACE=$(objpfx)tst-bz24228.mtrace
generated += test-fmemopen.mtrace test-fmemopen.check
generated += tst-fopenloc.mtrace tst-fopenloc.check
@@ -161,6 +170,7 @@ generated += tst-bz22415.mtrace tst-bz22415.check
aux := fileops genops stdfiles stdio strops
ifeq ($(build-shared),yes)
generated += tst-bz24228.mtrace tst-bz24228.check
aux += oldfileops oldstdfiles
endif
@@ -175,7 +185,8 @@ tests-special += $(objpfx)test-freopen.out $(objpfx)test-fmemopen-mem.out \
ifeq (yes,$(build-shared))
# Run tst-fopenloc-cmp.out and tst-openloc-mem.out only if shared
# library is enabled since they depend on tst-fopenloc.out.
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out
tests-special += $(objpfx)tst-fopenloc-cmp.out $(objpfx)tst-fopenloc-mem.out \
$(objpfx)tst-bz24228-mem.out
endif
endif
@@ -203,6 +214,7 @@ $(objpfx)tst-ungetwc1.out: $(gen-locales)
$(objpfx)tst-ungetwc2.out: $(gen-locales)
$(objpfx)tst-widetext.out: $(gen-locales)
$(objpfx)tst_wprintf2.out: $(gen-locales)
$(objpfx)tst-wfile-sync.out: $(gen-locales)
endif
$(objpfx)test-freopen.out: test-freopen.sh $(objpfx)test-freopen
@@ -226,3 +238,7 @@ $(objpfx)tst-fopenloc-mem.out: $(objpfx)tst-fopenloc.out
$(objpfx)tst-bz22415-mem.out: $(objpfx)tst-bz22415.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz22415.mtrace > $@; \
$(evaluate-test)
$(objpfx)tst-bz24228-mem.out: $(objpfx)tst-bz24228.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-bz24228.mtrace > $@; \
$(evaluate-test)
+12 -4
View File
@@ -852,9 +852,16 @@ _IO_unbuffer_all (void)
for (fp = (_IO_FILE *) _IO_list_all; fp; fp = fp->_chain)
{
int legacy = 0;
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (__glibc_unlikely (_IO_vtable_offset (fp) != 0))
legacy = 1;
#endif
if (! (fp->_flags & _IO_UNBUFFERED)
/* Iff stream is un-orientated, it wasn't used. */
&& fp->_mode != 0)
&& (legacy || fp->_mode != 0))
{
#ifdef _IO_MTSAFE_IO
int cnt;
@@ -868,7 +875,7 @@ _IO_unbuffer_all (void)
__sched_yield ();
#endif
if (! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
if (! legacy && ! dealloc_buffers && !(fp->_flags & _IO_USER_BUF))
{
fp->_flags |= _IO_USER_BUF;
@@ -879,7 +886,7 @@ _IO_unbuffer_all (void)
_IO_SETBUF (fp, NULL, 0);
if (fp->_mode > 0)
if (! legacy && fp->_mode > 0)
_IO_wsetb (fp, NULL, NULL, 0);
#ifdef _IO_MTSAFE_IO
@@ -890,7 +897,8 @@ _IO_unbuffer_all (void)
/* Make sure that never again the wide char functions can be
used. */
fp->_mode = -1;
if (! legacy)
fp->_mode = -1;
}
#ifdef _IO_MTSAFE_IO
+2 -2
View File
@@ -90,8 +90,8 @@ __open_memstream (char **bufloc, _IO_size_t *sizeloc)
_IO_JUMPS_FILE_plus (&new_f->fp._sf._sbf) = &_IO_mem_jumps;
_IO_str_init_static_internal (&new_f->fp._sf, buf, _IO_BUFSIZ, buf);
new_f->fp._sf._sbf._f._flags &= ~_IO_USER_BUF;
new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free;
new_f->fp.bufloc = bufloc;
new_f->fp.sizeloc = sizeloc;
+5
View File
@@ -87,6 +87,11 @@ _IO_check_libio (void)
stdout->_vtable_offset = stderr->_vtable_offset =
((int) sizeof (struct _IO_FILE)
- (int) sizeof (struct _IO_FILE_complete));
if (_IO_stdin_.vtable != &_IO_old_file_jumps
|| _IO_stdout_.vtable != &_IO_old_file_jumps
|| _IO_stderr_.vtable != &_IO_old_file_jumps)
IO_set_accept_foreign_vtables (&_IO_vtable_check);
}
}
+5 -6
View File
@@ -31,8 +31,11 @@ typedef void (*_IO_free_type) (void*);
struct _IO_str_fields
{
_IO_alloc_type _allocate_buffer;
_IO_free_type _free_buffer;
/* These members are preserved for ABI compatibility. The glibc
implementation always calls malloc/free for user buffers if
_IO_USER_BUF or _IO_FLAGS2_USER_WBUF are not set. */
_IO_alloc_type _allocate_buffer_unused;
_IO_free_type _free_buffer_unused;
};
/* This is needed for the Irix6 N32 ABI, which has a 64 bit off_t type,
@@ -52,10 +55,6 @@ typedef struct _IO_strfile_
struct _IO_str_fields _s;
} _IO_strfile;
/* dynamic: set when the array object is allocated (or reallocated) as
necessary to hold a character sequence that can change in length. */
#define _IO_STR_DYNAMIC(FP) ((FP)->_s._allocate_buffer != (_IO_alloc_type)0)
/* frozen: set when the program has requested that the array object not
be altered, reallocated, or freed. */
#define _IO_STR_FROZEN(FP) ((FP)->_f._IO_file_flags & _IO_USER_BUF)
+6 -8
View File
@@ -61,7 +61,7 @@ _IO_str_init_static_internal (_IO_strfile *sf, char *ptr, _IO_size_t size,
fp->_IO_read_end = end;
}
/* A null _allocate_buffer function flags the strfile as being static. */
sf->_s._allocate_buffer = (_IO_alloc_type) 0;
sf->_s._allocate_buffer_unused = (_IO_alloc_type) 0;
}
void
@@ -103,8 +103,7 @@ _IO_str_overflow (_IO_FILE *fp, int c)
_IO_size_t new_size = 2 * old_blen + 100;
if (new_size < old_blen)
return EOF;
new_buf
= (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
new_buf = malloc (new_size);
if (new_buf == NULL)
{
/* __ferror(fp) = 1; */
@@ -113,7 +112,7 @@ _IO_str_overflow (_IO_FILE *fp, int c)
if (old_buf)
{
memcpy (new_buf, old_buf, old_blen);
(*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
free (old_buf);
/* Make sure _IO_setb won't try to delete _IO_buf_base. */
fp->_IO_buf_base = NULL;
}
@@ -182,15 +181,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
_IO_size_t newsize = offset + 100;
char *oldbuf = fp->_IO_buf_base;
char *newbuf
= (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
char *newbuf = malloc (newsize);
if (newbuf == NULL)
return 1;
if (oldbuf != NULL)
{
memcpy (newbuf, oldbuf, _IO_blen (fp));
(*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
free (oldbuf);
/* Make sure _IO_setb won't try to delete
_IO_buf_base. */
fp->_IO_buf_base = NULL;
@@ -346,7 +344,7 @@ void
_IO_str_finish (_IO_FILE *fp, int dummy)
{
if (fp->_IO_buf_base && !(fp->_flags & _IO_USER_BUF))
(((_IO_strfile *) fp)->_s._free_buffer) (fp->_IO_buf_base);
free (fp->_IO_buf_base);
fp->_IO_buf_base = NULL;
_IO_default_finish (fp, 0);
+29
View File
@@ -0,0 +1,29 @@
/* BZ #24228 check for memory corruption in legacy libio
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <mcheck.h>
#include <support/test-driver.h>
static int
do_test (void)
{
mtrace ();
return 0;
}
#include <support/test-driver.c>
+5
View File
@@ -0,0 +1,5 @@
# Hide the symbol from libc.so.6 to switch to the libio/oldfileops.c
# implementation when it is available for the architecture.
{
local: _IO_stdin_used;
};
+511
View File
@@ -0,0 +1,511 @@
/* Test for libio vtables and their validation. Common code.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* This test provides some coverage for how various stdio functions
use the vtables in FILE * objects. The focus is mostly on which
functions call which methods, not so much on validating data
processing. An initial series of tests check that custom vtables
do not work without activation through _IO_init.
Note: libio vtables are deprecated feature. Do not use this test
as a documentation source for writing custom vtables. See
fopencookie for a different way of creating custom stdio
streams. */
#include <stdbool.h>
#include <string.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
#include <support/namespace.h>
#include <support/support.h>
#include <support/test-driver.h>
#include <support/xunistd.h>
/* Data shared between the test subprocess and the test driver in the
parent. Note that *shared is reset at the start of the check_call
function. */
struct shared
{
/* Expected file pointer for method calls. */
FILE *fp;
/* If true, assume that a call to _IO_init is needed to enable
custom vtables. */
bool initially_disabled;
/* Requested return value for the methods which have one. */
int return_value;
/* A value (usually a character) recorded by some of the methods
below. */
int value;
/* Likewise, for some data. */
char buffer[16];
size_t buffer_length;
/* Total number of method calls. */
unsigned int calls;
/* Individual method call counts. */
unsigned int calls_finish;
unsigned int calls_overflow;
unsigned int calls_underflow;
unsigned int calls_uflow;
unsigned int calls_pbackfail;
unsigned int calls_xsputn;
unsigned int calls_xsgetn;
unsigned int calls_seekoff;
unsigned int calls_seekpos;
unsigned int calls_setbuf;
unsigned int calls_sync;
unsigned int calls_doallocate;
unsigned int calls_read;
unsigned int calls_write;
unsigned int calls_seek;
unsigned int calls_close;
unsigned int calls_stat;
unsigned int calls_showmanyc;
unsigned int calls_imbue;
} *shared;
/* Method implementations which increment the counters in *shared. */
static void
log_method (FILE *fp, const char *name)
{
if (test_verbose > 0)
printf ("info: %s (%p) called\n", name, fp);
}
static void
method_finish (FILE *fp, int dummy)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_finish;
}
static int
method_overflow (FILE *fp, int ch)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_overflow;
shared->value = ch;
return shared->return_value;
}
static int
method_underflow (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_underflow;
return shared->return_value;
}
static int
method_uflow (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_uflow;
return shared->return_value;
}
static int
method_pbackfail (FILE *fp, int ch)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_pbackfail;
shared->value = ch;
return shared->return_value;
}
static size_t
method_xsputn (FILE *fp, const void *data, size_t n)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_xsputn;
size_t to_copy = n;
if (n > sizeof (shared->buffer))
to_copy = sizeof (shared->buffer);
memcpy (shared->buffer, data, to_copy);
shared->buffer_length = to_copy;
return to_copy;
}
static size_t
method_xsgetn (FILE *fp, void *data, size_t n)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_xsgetn;
return 0;
}
static off64_t
method_seekoff (FILE *fp, off64_t offset, int dir, int mode)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_seekoff;
return shared->return_value;
}
static off64_t
method_seekpos (FILE *fp, off64_t offset, int mode)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_seekpos;
return shared->return_value;
}
static FILE *
method_setbuf (FILE *fp, char *buffer, ssize_t length)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_setbuf;
return fp;
}
static int
method_sync (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_sync;
return shared->return_value;
}
static int
method_doallocate (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_doallocate;
return shared->return_value;
}
static ssize_t
method_read (FILE *fp, void *data, ssize_t length)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_read;
return shared->return_value;
}
static ssize_t
method_write (FILE *fp, const void *data, ssize_t length)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_write;
return shared->return_value;
}
static off64_t
method_seek (FILE *fp, off64_t offset, int mode)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_seek;
return shared->return_value;
}
static int
method_close (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_close;
return shared->return_value;
}
static int
method_stat (FILE *fp, void *buffer)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_stat;
return shared->return_value;
}
static int
method_showmanyc (FILE *fp)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_showmanyc;
return shared->return_value;
}
static void
method_imbue (FILE *fp, void *locale)
{
log_method (fp, __func__);
TEST_VERIFY (fp == shared->fp);
++shared->calls;
++shared->calls_imbue;
}
/* Our custom vtable. */
static const struct _IO_jump_t jumps =
{
JUMP_INIT_DUMMY,
JUMP_INIT (finish, method_finish),
JUMP_INIT (overflow, method_overflow),
JUMP_INIT (underflow, method_underflow),
JUMP_INIT (uflow, method_uflow),
JUMP_INIT (pbackfail, method_pbackfail),
JUMP_INIT (xsputn, method_xsputn),
JUMP_INIT (xsgetn, method_xsgetn),
JUMP_INIT (seekoff, method_seekoff),
JUMP_INIT (seekpos, method_seekpos),
JUMP_INIT (setbuf, method_setbuf),
JUMP_INIT (sync, method_sync),
JUMP_INIT (doallocate, method_doallocate),
JUMP_INIT (read, method_read),
JUMP_INIT (write, method_write),
JUMP_INIT (seek, method_seek),
JUMP_INIT (close, method_close),
JUMP_INIT (stat, method_stat),
JUMP_INIT (showmanyc, method_showmanyc),
JUMP_INIT (imbue, method_imbue)
};
/* Our file implementation. */
struct my_file
{
FILE f;
const struct _IO_jump_t *vtable;
};
struct my_file
my_file_create (void)
{
return (struct my_file)
{
/* Disable locking, so that we do not have to set up a lock
pointer. */
.f._flags = _IO_USER_LOCK,
/* Copy the offset from the an initialized handle, instead of
figuring it out from scratch. */
.f._vtable_offset = stdin->_vtable_offset,
.vtable = &jumps,
};
}
/* Initial tests which do not enable vtable compatibility. */
/* Inhibit GCC optimization of fprintf. */
typedef int (*fprintf_type) (FILE *, const char *, ...);
static const volatile fprintf_type fprintf_ptr = &fprintf;
static void
without_compatibility_fprintf (void *closure)
{
/* This call should abort. */
fprintf_ptr (shared->fp, " ");
_exit (1);
}
static void
without_compatibility_fputc (void *closure)
{
/* This call should abort. */
fputc (' ', shared->fp);
_exit (1);
}
static void
without_compatibility_fgetc (void *closure)
{
/* This call should abort. */
fgetc (shared->fp);
_exit (1);
}
static void
without_compatibility_fflush (void *closure)
{
/* This call should abort. */
fflush (shared->fp);
_exit (1);
}
/* Exit status after abnormal termination. */
static int termination_status;
static void
init_termination_status (void)
{
pid_t pid = xfork ();
if (pid == 0)
abort ();
xwaitpid (pid, &termination_status, 0);
TEST_VERIFY (WIFSIGNALED (termination_status));
TEST_COMPARE (WTERMSIG (termination_status), SIGABRT);
}
static void
check_for_termination (const char *name, void (*callback) (void *))
{
struct my_file file = my_file_create ();
shared->fp = &file.f;
shared->return_value = -1;
shared->calls = 0;
struct support_capture_subprocess proc
= support_capture_subprocess (callback, NULL);
support_capture_subprocess_check (&proc, name, termination_status,
sc_allow_stderr);
const char *message
= "Fatal error: glibc detected an invalid stdio handle\n";
TEST_COMPARE_BLOB (proc.err.buffer, proc.err.length,
message, strlen (message));
TEST_COMPARE (shared->calls, 0);
support_capture_subprocess_free (&proc);
}
/* The test with vtable validation disabled. */
/* This function does not have a prototype in libioP.h to prevent
accidental use from within the library (which would disable vtable
verification). */
void _IO_init (FILE *fp, int flags);
static void
with_compatibility_fprintf (void *closure)
{
TEST_COMPARE (fprintf_ptr (shared->fp, "A%sCD", "B"), 4);
TEST_COMPARE (shared->calls, 3);
TEST_COMPARE (shared->calls_xsputn, 3);
TEST_COMPARE_BLOB (shared->buffer, shared->buffer_length,
"CD", 2);
}
static void
with_compatibility_fputc (void *closure)
{
shared->return_value = '@';
TEST_COMPARE (fputc ('@', shared->fp), '@');
TEST_COMPARE (shared->calls, 1);
TEST_COMPARE (shared->calls_overflow, 1);
TEST_COMPARE (shared->value, '@');
}
static void
with_compatibility_fgetc (void *closure)
{
shared->return_value = 'X';
TEST_COMPARE (fgetc (shared->fp), 'X');
TEST_COMPARE (shared->calls, 1);
TEST_COMPARE (shared->calls_uflow, 1);
}
static void
with_compatibility_fflush (void *closure)
{
TEST_COMPARE (fflush (shared->fp), 0);
TEST_COMPARE (shared->calls, 1);
TEST_COMPARE (shared->calls_sync, 1);
}
/* Call CALLBACK in a subprocess, after setting up a custom file
object and updating shared->fp. */
static void
check_call (const char *name, void (*callback) (void *),
bool initially_disabled)
{
*shared = (struct shared)
{
.initially_disabled = initially_disabled,
};
/* Set up a custom file object. */
struct my_file file = my_file_create ();
shared->fp = &file.f;
if (shared->initially_disabled)
_IO_init (shared->fp, file.f._flags);
if (test_verbose > 0)
printf ("info: calling test %s\n", name);
support_isolate_in_subprocess (callback, NULL);
}
/* Run the tests. INITIALLY_DISABLED indicates whether custom vtables
are disabled when the test starts. */
static int
run_tests (bool initially_disabled)
{
/* The test relies on fatal error messages being printed to standard
error. */
setenv ("LIBC_FATAL_STDERR_", "1", 1);
shared = support_shared_allocate (sizeof (*shared));
shared->initially_disabled = initially_disabled;
init_termination_status ();
if (initially_disabled)
{
check_for_termination ("fprintf", without_compatibility_fprintf);
check_for_termination ("fputc", without_compatibility_fputc);
check_for_termination ("fgetc", without_compatibility_fgetc);
check_for_termination ("fflush", without_compatibility_fflush);
}
check_call ("fprintf", with_compatibility_fprintf, initially_disabled);
check_call ("fputc", with_compatibility_fputc, initially_disabled);
check_call ("fgetc", with_compatibility_fgetc, initially_disabled);
check_call ("fflush", with_compatibility_fflush, initially_disabled);
support_shared_free (shared);
shared = NULL;
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
/* Test for libio vtables and their validation. Enabled through interposition.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
/* Provide an interposed definition of the standard file handles with
our own vtable. stdout/stdin/stderr will not work as a result, but
a succesful test does not print anything, so this is fine. */
static const struct _IO_jump_t jumps;
#define _IO_file_jumps jumps
#include "stdfiles.c"
#include "tst-vtables-common.c"
static int
do_test (void)
{
return run_tests (false);
}
/* Calling setvbuf in the test driver is not supported with our
interposed file handles. */
#define TEST_NO_SETVBUF
#include <support/test-driver.c>
+29
View File
@@ -0,0 +1,29 @@
/* Test for libio vtables and their validation. Initially disabled case.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include "libioP.h"
#include "tst-vtables-common.c"
static int
do_test (void)
{
return run_tests (true);
}
#include <support/test-driver.c>
+39
View File
@@ -0,0 +1,39 @@
/* Test that _IO_wfile_sync does not crash (bug 20568).
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <locale.h>
#include <stdio.h>
#include <wchar.h>
#include <support/check.h>
#include <support/xunistd.h>
static int
do_test (void)
{
TEST_VERIFY_EXIT (setlocale (LC_ALL, "de_DE.UTF-8") != NULL);
/* Fill the stdio buffer and advance the read pointer. */
TEST_VERIFY_EXIT (fgetwc (stdin) != WEOF);
/* This calls _IO_wfile_sync, it should not crash. */
TEST_VERIFY_EXIT (setvbuf (stdin, NULL, _IONBF, 0) == 0);
/* Verify that the external file offset has been synchronized. */
TEST_COMPARE (xlseek (0, 0, SEEK_CUR), 1);
return 0;
}
#include <support/test-driver.c>
+1
View File
@@ -0,0 +1 @@
This is a test of _IO_wfile_sync.
+2 -2
View File
@@ -54,8 +54,8 @@ _IO_vasprintf (char **result_ptr, const char *format, _IO_va_list args)
_IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
_IO_str_init_static_internal (&sf, string, init_string_size, string);
sf._sbf._f._flags &= ~_IO_USER_BUF;
sf._s._allocate_buffer = (_IO_alloc_type) malloc;
sf._s._free_buffer = (_IO_free_type) free;
sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
sf._s._free_buffer_unused = (_IO_free_type) free;
ret = _IO_vfprintf (&sf._sbf._f, format, args);
if (ret < 0)
{
+16
View File
@@ -71,3 +71,19 @@ _IO_vtable_check (void)
__libc_fatal ("Fatal error: glibc detected an invalid stdio handle\n");
}
/* Some variants of libstdc++ interpose _IO_2_1_stdin_ etc. and
install their own vtables directly, without calling _IO_init or
other functions. Detect this by looking at the vtables values
during startup, and disable vtable validation in this case. */
#ifdef SHARED
__attribute__ ((constructor))
static void
check_stdfiles_vtables (void)
{
if (_IO_2_1_stdin_.vtable != &_IO_file_jumps
|| _IO_2_1_stdout_.vtable != &_IO_file_jumps
|| _IO_2_1_stderr_.vtable != &_IO_file_jumps)
IO_set_accept_foreign_vtables (&_IO_vtable_check);
}
#endif
+3 -2
View File
@@ -509,11 +509,12 @@ _IO_wfile_sync (_IO_FILE *fp)
generate the wide characters up to the current reading
position. */
int nread;
size_t wnread = (fp->_wide_data->_IO_read_ptr
- fp->_wide_data->_IO_read_base);
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
fp->_IO_read_base,
fp->_IO_read_end, delta);
fp->_IO_read_end, wnread);
fp->_IO_read_ptr = fp->_IO_read_base + nread;
delta = -(fp->_IO_read_end - fp->_IO_read_base - nread);
}
+2 -2
View File
@@ -92,8 +92,8 @@ open_wmemstream (wchar_t **bufloc, _IO_size_t *sizeloc)
_IO_wstr_init_static (&new_f->fp._sf._sbf._f, buf,
_IO_BUFSIZ / sizeof (wchar_t), buf);
new_f->fp._sf._sbf._f._flags2 &= ~_IO_FLAGS2_USER_WBUF;
new_f->fp._sf._s._allocate_buffer = (_IO_alloc_type) malloc;
new_f->fp._sf._s._free_buffer = (_IO_free_type) free;
new_f->fp._sf._s._allocate_buffer_unused = (_IO_alloc_type) malloc;
new_f->fp._sf._s._free_buffer_unused = (_IO_free_type) free;
new_f->fp.bufloc = bufloc;
new_f->fp.sizeloc = sizeloc;
+6 -10
View File
@@ -63,7 +63,7 @@ _IO_wstr_init_static (_IO_FILE *fp, wchar_t *ptr, _IO_size_t size,
fp->_wide_data->_IO_read_end = end;
}
/* A null _allocate_buffer function flags the strfile as being static. */
(((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
(((_IO_strfile *) fp)->_s._allocate_buffer_unused) = (_IO_alloc_type)0;
}
_IO_wint_t
@@ -95,9 +95,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c)
|| __glibc_unlikely (new_size > SIZE_MAX / sizeof (wchar_t)))
return EOF;
new_buf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
* sizeof (wchar_t));
new_buf = malloc (new_size * sizeof (wchar_t));
if (new_buf == NULL)
{
/* __ferror(fp) = 1; */
@@ -106,7 +104,7 @@ _IO_wstr_overflow (_IO_FILE *fp, _IO_wint_t c)
if (old_buf)
{
__wmemcpy (new_buf, old_buf, old_wblen);
(*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
free (old_buf);
/* Make sure _IO_setb won't try to delete _IO_buf_base. */
fp->_wide_data->_IO_buf_base = NULL;
}
@@ -186,16 +184,14 @@ enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
return 1;
wchar_t *oldbuf = wd->_IO_buf_base;
wchar_t *newbuf
= (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
* sizeof (wchar_t));
wchar_t *newbuf = malloc (newsize * sizeof (wchar_t));
if (newbuf == NULL)
return 1;
if (oldbuf != NULL)
{
__wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
(*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
free (oldbuf);
/* Make sure _IO_setb won't try to delete
_IO_buf_base. */
wd->_IO_buf_base = NULL;
@@ -357,7 +353,7 @@ void
_IO_wstr_finish (_IO_FILE *fp, int dummy)
{
if (fp->_wide_data->_IO_buf_base && !(fp->_flags2 & _IO_FLAGS2_USER_WBUF))
(((_IO_strfile *) fp)->_s._free_buffer) (fp->_wide_data->_IO_buf_base);
free (fp->_wide_data->_IO_buf_base);
fp->_wide_data->_IO_buf_base = NULL;
_IO_wdefault_finish (fp, 0);
+3 -1
View File
@@ -78,7 +78,7 @@ tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
tst-wctype
tst-wctype tst-iconv-math-trans
tests-static = bug-setlocale1-static
tests += $(tests-static)
ifeq (yes,$(build-shared))
@@ -113,6 +113,8 @@ LOCALES := de_DE.ISO-8859-1 de_DE.UTF-8 en_US.ANSI_X3.4-1968 \
pl_PL.UTF-8 fr_CA.UTF-8 hr_HR.UTF-8 bs_BA.UTF-8 sr_RS.UTF-8 \
is_IS.UTF-8 et_EE.UTF-8 hsb_DE.UTF-8 lt_LT.UTF-8
include ../gen-locales.mk
$(objpfx)tst-iconv-math-trans.out: $(gen-locales)
endif
include ../Rules
+71 -40
View File
@@ -106,36 +106,67 @@ grouping 0;0
END LC_NUMERIC
LC_TIME
abday "dg";"dl";"dt";"dc";"dj";"dv";"ds"
day "diumenge";/
"dilluns";/
"dimarts";/
"dimecres";/
"dijous";/
"divendres";/
"dissabte"
abmon "gen";"feb";/
"mar";"abr";/
"mai";"jun";/
"jul";"ago";/
"set";"oct";/
"nov";"des"
mon "gener";/
"febrer";/
"mar<U00E7>";/
"abril";/
"maig";/
"juny";/
"juliol";/
"agost";/
"setembre";/
"octubre";/
"novembre";/
"desembre"
d_t_fmt "%a %d %b %Y %T %Z"
d_fmt "%d//%m//%y"
t_fmt "%T"
am_pm "";""
abday "dg.";"dl.";"dt.";"dc.";"dj.";"dv.";"ds."
day "diumenge";/
"dilluns";/
"dimarts";/
"dimecres";/
"dijous";/
"divendres";/
"dissabte"
ab_alt_mon "gen.";/
"febr.";/
"mar<U00E7>";/
"abr.";/
"maig";/
"juny";/
"jul.";/
"ag.";/
"set.";/
"oct.";/
"nov.";/
"des."
abmon "de gen.";/
"de febr.";/
"de mar<U00E7>";/
"d<U2019>abr.";/
"de maig";/
"de juny";/
"de jul.";/
"d<U2019>ag.";/
"de set.";/
"d<U2019>oct.";/
"de nov.";/
"de des."
alt_mon "gener";/
"febrer";/
"mar<U00E7>";/
"abril";/
"maig";/
"juny";/
"juliol";/
"agost";/
"setembre";/
"octubre";/
"novembre";/
"desembre"
mon "de gener";/
"de febrer";/
"de mar<U00E7>";/
"d<U2019>abril";/
"de maig";/
"de juny";/
"de juliol";/
"d<U2019>agost";/
"de setembre";/
"d<U2019>octubre";/
"de novembre";/
"de desembre"
d_t_fmt "%A, %-d %B de %Y, %T %Z"
d_fmt "%-d//%-m//%y"
t_fmt "%T"
am_pm "a. m.";/
"p. m."
t_fmt_ampm ""
week 7;19971130;4
first_weekday 2
@@ -146,9 +177,9 @@ copy "i18n"
END LC_PAPER
LC_TELEPHONE
tel_int_fmt "+%c %a %l"
int_prefix "34"
int_select "00"
tel_int_fmt "+%c %a %l"
int_prefix "34"
int_select "00"
END LC_TELEPHONE
LC_MEASUREMENT
@@ -156,19 +187,19 @@ copy "i18n"
END LC_MEASUREMENT
LC_NAME
name_fmt "%d%t%g%t%m%t%f"
name_fmt "%d%t%g%t%m%t%f"
END LC_NAME
LC_ADDRESS
postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N"
postal_fmt "%f%N%a%N%d%N%b%N%s %h %e %r%N%z %T%N%c%N"
country_name "Espanya"
country_ab2 "ES"
country_ab3 "ESP"
country_num 724
country_car "E"
country_ab2 "ES"
country_ab3 "ESP"
country_num 724
country_car "E"
% català
lang_name "catal<U00E0>"
lang_ab "ca"
lang_term "cat"
lang_lib "cat"
lang_lib "cat"
END LC_ADDRESS
+14 -1
View File
@@ -272,7 +272,7 @@ day "Ned<U011B>le";/
"P<U00E1>tek";/
"Sobota"
mon "leden";/
alt_mon "leden";/
"<U00FA>nor";/
"b<U0159>ezen";/
"duben";/
@@ -334,6 +334,19 @@ abmon "led";/
% "Nov";/
% "Dec"
mon "ledna";/
"<U00FA>nora";/
"b<U0159>ezna";/
"dubna";/
"kv<U011B>tna";/
"<U010D>ervna";/
"<U010D>ervence";/
"srpna";/
"z<U00E1><U0159><U00ED>";/
"<U0159><U00ED>jna";/
"listopadu";/
"prosince"
week 7;19971130;4
first_weekday 2
+7 -1
View File
@@ -72,12 +72,18 @@ day "<U039A><U03C5><U03C1><U03B9><U03B1><U03BA><U03AE>";/
"<U03A0><U03AD><U03BC><U03C0><U03C4><U03B7>";/
"<U03A0><U03B1><U03C1><U03B1><U03C3><U03BA><U03B5><U03C5><U03AE>";/
"<U03A3><U03AC><U03B2><U03B2><U03B1><U03C4><U03BF>"
abmon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
ab_alt_mon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
"<U039C><U03AC><U03C1>";"<U0391><U03C0><U03C1>";/
"<U039C><U03AC><U03B9>";"<U0399><U03BF><U03CD><U03BD>";/
"<U0399><U03BF><U03CD><U03BB>";"<U0391><U03CD><U03B3>";/
"<U03A3><U03B5><U03C0>";"<U039F><U03BA><U03C4>";/
"<U039D><U03BF><U03AD>";"<U0394><U03B5><U03BA>"
abmon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
"<U039C><U03B1><U03C1>";"<U0391><U03C0><U03C1>";/
"<U039C><U03B1><U0390>";"<U0399><U03BF><U03C5><U03BD>";/
"<U0399><U03BF><U03C5><U03BB>";"<U0391><U03C5><U03B3>";/
"<U03A3><U03B5><U03C0>";"<U039F><U03BA><U03C4>";/
"<U039D><U03BF><U03B5>";"<U0394><U03B5><U03BA>"
alt_mon "<U0399><U03B1><U03BD><U03BF><U03C5><U03AC><U03C1><U03B9><U03BF><U03C2>";/
"<U03A6><U03B5><U03B2><U03C1><U03BF><U03C5><U03AC><U03C1><U03B9><U03BF><U03C2>";/
"<U039C><U03AC><U03C1><U03C4><U03B9><U03BF><U03C2>";/
+7 -1
View File
@@ -104,12 +104,18 @@ day "<U039A><U03C5><U03C1><U03B9><U03B1><U03BA><U03AE>";/
"<U03A0><U03AD><U03BC><U03C0><U03C4><U03B7>";/
"<U03A0><U03B1><U03C1><U03B1><U03C3><U03BA><U03B5><U03C5><U03AE>";/
"<U03A3><U03AC><U03B2><U03B2><U03B1><U03C4><U03BF>"
abmon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
ab_alt_mon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
"<U039C><U03AC><U03C1>";"<U0391><U03C0><U03C1>";/
"<U039C><U03AC><U03B9>";"<U0399><U03BF><U03CD><U03BD>";/
"<U0399><U03BF><U03CD><U03BB>";"<U0391><U03CD><U03B3>";/
"<U03A3><U03B5><U03C0>";"<U039F><U03BA><U03C4>";/
"<U039D><U03BF><U03AD>";"<U0394><U03B5><U03BA>"
abmon "<U0399><U03B1><U03BD>";"<U03A6><U03B5><U03B2>";/
"<U039C><U03B1><U03C1>";"<U0391><U03C0><U03C1>";/
"<U039C><U03B1><U0390>";"<U0399><U03BF><U03C5><U03BD>";/
"<U0399><U03BF><U03C5><U03BB>";"<U0391><U03C5><U03B3>";/
"<U03A3><U03B5><U03C0>";"<U039F><U03BA><U03C4>";/
"<U039D><U03BF><U03B5>";"<U0394><U03B5><U03BA>"
alt_mon "<U0399><U03B1><U03BD><U03BF><U03C5><U03AC><U03C1><U03B9><U03BF><U03C2>";/
"<U03A6><U03B5><U03B2><U03C1><U03BF><U03C5><U03AC><U03C1><U03B9><U03BF><U03C2>";/
"<U039C><U03AC><U03C1><U03C4><U03B9><U03BF><U03C2>";/
+1 -1
View File
@@ -124,7 +124,7 @@ first_weekday 2
END LC_TIME
LC_PAPER
copy "i18n"
copy "en_US"
END LC_PAPER
LC_TELEPHONE
+2
View File
@@ -103,6 +103,8 @@ reorder-after <w>
<U00FC> <u-diaresis>;<BAS>;<MIN>;IGNORE % ü
<U00DC> <u-diaresis>;<BAS>;<CAP>;IGNORE % Ü
reorder-end
END LC_COLLATE
LC_CTYPE
+2 -2
View File
@@ -66,12 +66,12 @@ mon "Am Faoilleach";/
"An D<U00E0>mhair";/
"An t-Samhain";/
"An D<U00F9>bhlachd"
% Faoi, Gearr, Màrt, Gibl, Mhàrt, Ògmh, Iuch, Lùna, Sult, Dàmh, Samh, Dùbh
% Faoi, Gearr, Màrt, Gibl, Cèit, Ògmh, Iuch, Lùna, Sult, Dàmh, Samh, Dùbh
abmon "Faoi";/
"Gearr";/
"M<U00E0>rt";/
"Gibl";/
"Mh<U00E0>rt";/
"C<U00E8>it";/
"<U00D2>gmh";/
"Iuch";/
"L<U00F9>na";/
+3 -1
View File
@@ -14946,7 +14946,9 @@ am_pm "<U5348><U524D>";"<U5348><U5F8C>"
t_fmt_ampm "%p%I<U6642>%M<U5206>%S<U79D2>"
era "+:2:1990//01//01:+*:<U5E73><U6210>:%EC%Ey<U5E74>";/
era "+:2:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74>";/
"+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74>";/
"+:2:1990//01//01:2019//04//30:<U5E73><U6210>:%EC%Ey<U5E74>";/
"+:1:1989//01//08:1989//12//31:<U5E73><U6210>:%EC<U5143><U5E74>";/
"+:2:1927//01//01:1989//01//07:<U662D><U548C>:%EC%Ey<U5E74>";/
"+:1:1926//12//25:1926//12//31:<U662D><U548C>:%EC<U5143><U5E74>";/
+6 -6
View File
@@ -201,12 +201,12 @@ day "Sekmadienis";/
"Ketvirtadienis";/
"Penktadienis";/
"<U0160>e<U0161>tadienis"
abmon "Sau";"Vas";/
"Kov";"Bal";/
"Geg";"Bir";/
"Lie";"Rgp";/
"Rgs";"Spa";/
"Lap";"Grd"
abmon "saus.";"vas.";/
"kov.";"bal.";/
"geg.";"bir<U017E>.";/
"liep.";"rugp.";/
"rugs.";"spal.";/
"lapkr.";"gruod."
alt_mon "sausis";/
"vasaris";/
"kovas";/
+50 -2
View File
@@ -743,10 +743,22 @@ include "translit_wide";""
<U263A> "<U003A><U0029>"
% BLACK SMILING FACE
<U263B> "<U003A><U0029>"
% MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
<U27EB> "<U003E><U003E>"
% MATHEMATICAL LEFT WHITE SQUARE BRACKET
<U27E6> "<U005B><U007C>"
% MATHEMATICAL RIGHT WHITE SQUARE BRACKET
<U27E7> "<U007C><U005D>"
% MATHEMATICAL LEFT ANGLE BRACKET
<U27E8> <U003C>
% MATHEMATICAL RIGHT ANGLE BRACKET
<U27E9> <U003E>
% MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
<U27EA> "<U003C><U003C>"
% MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
<U27EB> "<U003E><U003E>"
% MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
<U27EC> "<U0028><U0028>"
% MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
<U27ED> "<U0029><U0029>"
% MATHEMATICAL LEFT FLATTENED PARENTHESIS
<U27EE> <U0028>
% MATHEMATICAL RIGHT FLATTENED PARENTHESIS
@@ -755,6 +767,42 @@ include "translit_wide";""
<U27CB> <U002F>
% MATHEMATICAL FALLING DIAGONAL
<U27CD> <U005C>
% TRIPLE VERTICAL BAR DELIMITER
<U2980> "<U007C><U007C><U007C>"
% LEFT WHITE CURLY BRACKET
<U2983> "<U007B><U007C>"
% RIGHT WHITE CURLY BRACKET
<U2984> "<U007C><U007D>"
% LEFT WHITE PARENTHESIS
<U2985> "<U0028><U0028>"
% RIGHT WHITE PARENTHESIS
<U2986> "<U0029><U0029>"
% Z NOTATION LEFT IMAGE BRACKET
<U2987> "<U0028><U007C>"
% Z NOTATION RIGHT IMAGE BRACKET
<U2988> "<U007C><U0029>"
% Z NOTATION LEFT BINDING BRACKET
<U2989> "<U003C><U007C>"
% Z NOTATION RIGHT BINDING BRACKET
<U298A> "<U007C><U003E>"
% EQUALS SIGN AND SLANTED PARALLEL
<U29E3> <U0023>
% IDENTICAL TO AND SLANTED PARALLEL
<U29E5> <U0023>
% REVERSE SOLIDUS OPERATOR
<U29F5> <U005C>
% BIG SOLIDUS
<U29F8> <U002F>
% BIG REVERSE SOLIDUS
<U29F9> <U005C>
% LEFT-POINTING CURVED ANGLE BRACKET
<U29FC> <U003C>
% RIGHT-POINTING CURVED ANGLE BRACKET
<U29FD> <U003E>
% TINY
<U29FE> <U002B>
% MINY
<U29FF> <U002D>
% LEFT ANGLE BRACKET
<U3008> <U003C>
% RIGHT ANGLE BRACKET
+104
View File
@@ -0,0 +1,104 @@
/* Test some mathematical operator transliterations (BZ #23132)
Copyright (C) 2019 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#include <iconv.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <support/check.h>
static int
do_test (void)
{
iconv_t cd;
/* str[] = "⟦ ⟧ ⟨ ⟩"
" ⟬ ⟭ ⦀"
" ⦃ ⦄ ⦅ ⦆"
" ⦇ ⦈ ⦉ ⦊"
" ⧣ ⧥ "
" ⧼ ⧽ ⧾ ⧿"; */
const char str[] = "\u27E6 \u27E7 \u27E8 \u27E9"
" \u27EC \u27ED \u2980"
" \u2983 \u2984 \u2985 \u2986"
" \u2987 \u2988 \u2989 \u298A"
" \u29E3 \u29E5 \u29F5 \u29F8 \u29F9"
" \u29FC \u29FD \u29FE \u29FF";
const char expected[] = "[| |] < >"
" (( )) |||"
" {| |} (( ))"
" (| |) <| |>"
" # # \\ / \\"
" < > + -";
char *inptr = (char *) str;
size_t inlen = strlen (str) + 1;
char outbuf[500];
char *outptr = outbuf;
size_t outlen = sizeof (outbuf);
int result = 0;
size_t n;
if (setlocale (LC_ALL, "en_US.UTF-8") == NULL)
FAIL_EXIT1 ("setlocale failed");
cd = iconv_open ("ASCII//TRANSLIT", "UTF-8");
if (cd == (iconv_t) -1)
FAIL_EXIT1 ("iconv_open failed");
n = iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (n != 24)
{
if (n == (size_t) -1)
printf ("iconv() returned error: %m\n");
else
printf ("iconv() returned %Zd, expected 24\n", n);
result = 1;
}
if (inlen != 0)
{
puts ("not all input consumed");
result = 1;
}
else if (inptr - str != strlen (str) + 1)
{
printf ("inptr wrong, advanced by %td\n", inptr - str);
result = 1;
}
if (memcmp (outbuf, expected, sizeof (expected)) != 0)
{
printf ("result wrong: \"%.*s\", expected: \"%s\"\n",
(int) (sizeof (outbuf) - outlen), outbuf, expected);
result = 1;
}
else if (outlen != sizeof (outbuf) - sizeof (expected))
{
printf ("outlen wrong: %Zd, expected %Zd\n", outlen,
sizeof (outbuf) - 15);
result = 1;
}
else
printf ("output is \"%s\" which is OK\n", outbuf);
return result;
}
#include <support/test-driver.c>
+1
View File
@@ -37,6 +37,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
tst-malloc-tcache-leak \
tst-malloc_info \
tst-malloc-too-large \
tst-tcfree1 tst-tcfree2 tst-tcfree3 \
tests-static := \
tst-interpose-static-nothread \
+42 -50
View File
@@ -2904,6 +2904,8 @@ mremap_chunk (mchunkptr p, size_t new_size)
typedef struct tcache_entry
{
struct tcache_entry *next;
/* This field exists to detect double frees. */
struct tcache_perthread_struct *key;
} tcache_entry;
/* There is one of these for each thread, which contains the
@@ -2917,6 +2919,8 @@ typedef struct tcache_perthread_struct
tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct;
#define MAX_TCACHE_COUNT 127 /* Maximum value of counts[] entries. */
static __thread bool tcache_shutting_down = false;
static __thread tcache_perthread_struct *tcache = NULL;
@@ -2927,6 +2931,11 @@ tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry *e = (tcache_entry *) chunk2mem (chunk);
assert (tc_idx < TCACHE_MAX_BINS);
/* Mark this chunk as "in the tcache" so the test in _int_free will
detect a double free. */
e->key = tcache;
e->next = tcache->entries[tc_idx];
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
@@ -2942,6 +2951,7 @@ tcache_get (size_t tc_idx)
assert (tcache->entries[tc_idx] > 0);
tcache->entries[tc_idx] = e->next;
--(tcache->counts[tc_idx]);
e->key = NULL;
return (void *) e;
}
@@ -4165,13 +4175,33 @@ _int_free (mstate av, mchunkptr p, int have_lock)
#if USE_TCACHE
{
size_t tc_idx = csize2tidx (size);
if (tcache
&& tc_idx < mp_.tcache_bins
&& tcache->counts[tc_idx] < mp_.tcache_count)
if (tcache != NULL && tc_idx < mp_.tcache_bins)
{
tcache_put (p, tc_idx);
return;
/* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache))
{
tcache_entry *tmp;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx];
tmp;
tmp = tmp->next)
if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */
}
if (tcache->counts[tc_idx] < mp_.tcache_count)
{
tcache_put (p, tc_idx);
return;
}
}
}
#endif
@@ -4512,11 +4542,6 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
unsigned long copysize; /* bytes to copy */
unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */
INTERNAL_SIZE_T* s; /* copy source */
INTERNAL_SIZE_T* d; /* copy destination */
/* oldmem size */
if (__builtin_expect (chunksize_nomask (oldp) <= 2 * SIZE_SZ, 0)
|| __builtin_expect (oldsize >= av->system_mem, 0))
@@ -4584,43 +4609,7 @@ _int_realloc(mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
}
else
{
/*
Unroll copy of <= 36 bytes (72 if 8byte sizes)
We know that contents have an odd number of
INTERNAL_SIZE_T-sized words; minimally 3.
*/
copysize = oldsize - SIZE_SZ;
s = (INTERNAL_SIZE_T *) (chunk2mem (oldp));
d = (INTERNAL_SIZE_T *) (newmem);
ncopies = copysize / sizeof (INTERNAL_SIZE_T);
assert (ncopies >= 3);
if (ncopies > 9)
memcpy (d, s, copysize);
else
{
*(d + 0) = *(s + 0);
*(d + 1) = *(s + 1);
*(d + 2) = *(s + 2);
if (ncopies > 4)
{
*(d + 3) = *(s + 3);
*(d + 4) = *(s + 4);
if (ncopies > 6)
{
*(d + 5) = *(s + 5);
*(d + 6) = *(s + 6);
if (ncopies > 8)
{
*(d + 7) = *(s + 7);
*(d + 8) = *(s + 8);
}
}
}
}
memcpy (newmem, chunk2mem (oldp), oldsize - SIZE_SZ);
_int_free (av, oldp, 1);
check_inuse_chunk (av, newp);
return chunk2mem (newp);
@@ -5118,8 +5107,11 @@ static inline int
__always_inline
do_set_tcache_count (size_t value)
{
LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
mp_.tcache_count = value;
if (value <= MAX_TCACHE_COUNT)
{
LIBC_PROBE (memory_tunable_tcache_count, 2, value, mp_.tcache_count);
mp_.tcache_count = value;
}
return 1;
}
+42
View File
@@ -0,0 +1,42 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <limits.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/signal.h>
static int
do_test (void)
{
/* Do one allocation of any size that fits in tcache. */
char * volatile x = malloc (32);
free (x); // puts in tcache
free (x); // should abort
printf("FAIL: tcache double free not detected\n");
return 1;
}
#define TEST_FUNCTION do_test
#define EXPECTED_SIGNAL SIGABRT
#include <support/test-driver.c>
+48
View File
@@ -0,0 +1,48 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <limits.h>
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/signal.h>
static int
do_test (void)
{
char * volatile ptrs[20];
int i;
/* Allocate enough small chunks so that when we free them all, the tcache
is full, and the first one we freed is at the end of its linked list. */
#define COUNT 20
for (i=0; i<COUNT; i++)
ptrs[i] = malloc (20);
for (i=0; i<COUNT; i++)
free (ptrs[i]);
free (ptrs[0]);
printf("FAIL: tcache double free\n");
return 1;
}
#define TEST_FUNCTION do_test
#define EXPECTED_SIGNAL SIGABRT
#include <support/test-driver.c>
+56
View File
@@ -0,0 +1,56 @@
/* Test that malloc tcache catches double free.
Copyright (C) 2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <malloc.h>
#include <string.h>
/* Prevent GCC from optimizing away any malloc/free pairs. */
#pragma GCC optimize ("O0")
static int
do_test (void)
{
/* Do two allocation of any size that fit in tcache, and one that
doesn't. */
int ** volatile a = malloc (32);
int ** volatile b = malloc (32);
/* This is just under the mmap threshold. */
int ** volatile c = malloc (127 * 1024);
/* The invalid "tcache bucket" we might dereference will likely end
up somewhere within this memory block, so make all the accidental
"next" pointers cause segfaults. BZ #23907. */
memset (c, 0xff, 127 * 1024);
free (a); // puts in tcache
/* A is now free and contains the key we use to detect in-tcache.
Copy the key to the other chunks. */
memcpy (b, a, 32);
memcpy (c, a, 32);
/* This free tests the "are we in the tcache already" loop with a
VALID bin but "coincidental" matching key. */
free (b); // should NOT abort
/* This free tests the "is it a valid tcache bin" test. */
free (c); // should NOT abort
return 0;
}
#include <support/test-driver.c>
+40 -52
View File
@@ -643,8 +643,8 @@ and they also do not require it to be in the initial state.
@cindex stateful
The @code{mbrtowc} function (``multibyte restartable to wide
character'') converts the next multibyte character in the string pointed
to by @var{s} into a wide character and stores it in the wide character
string pointed to by @var{pwc}. The conversion is performed according
to by @var{s} into a wide character and stores it in the location
pointed to by @var{pwc}. The conversion is performed according
to the locale currently selected for the @code{LC_CTYPE} category. If
the conversion for the character set used in the locale requires a state,
the multibyte string is interpreted in the state represented by the
@@ -652,7 +652,7 @@ object pointed to by @var{ps}. If @var{ps} is a null pointer, a static,
internal state variable used only by the @code{mbrtowc} function is
used.
If the next multibyte character corresponds to the NUL wide character,
If the next multibyte character corresponds to the null wide character,
the return value of the function is @math{0} and the state object is
afterwards in the initial state. If the next @var{n} or fewer bytes
form a correct multibyte character, the return value is the number of
@@ -665,71 +665,59 @@ by @var{pwc} if @var{pwc} is not null.
If the first @var{n} bytes of the multibyte string possibly form a valid
multibyte character but there are more than @var{n} bytes needed to
complete it, the return value of the function is @code{(size_t) -2} and
no value is stored. Please note that this can happen even if @var{n}
has a value greater than or equal to @code{MB_CUR_MAX} since the input
might contain redundant shift sequences.
no value is stored in @code{*@var{pwc}}. The conversion state is
updated and all @var{n} input bytes are consumed and should not be
submitted again. Please note that this can happen even if @var{n} has a
value greater than or equal to @code{MB_CUR_MAX} since the input might
contain redundant shift sequences.
If the first @code{n} bytes of the multibyte string cannot possibly form
a valid multibyte character, no value is stored, the global variable
@code{errno} is set to the value @code{EILSEQ}, and the function returns
@code{(size_t) -1}. The conversion state is afterwards undefined.
As specified, the @code{mbrtowc} function could deal with multibyte
sequences which contain embedded null bytes (which happens in Unicode
encodings such as UTF-16), but @theglibc{} does not support such
multibyte encodings. When encountering a null input byte, the function
will either return zero, or return @code{(size_t) -1)} and report a
@code{EILSEQ} error. The @code{iconv} function can be used for
converting between arbitrary encodings. @xref{Generic Conversion
Interface}.
@pindex wchar.h
@code{mbrtowc} was introduced in @w{Amendment 1} to @w{ISO C90} and
is declared in @file{wchar.h}.
@end deftypefun
Use of @code{mbrtowc} is straightforward. A function that copies a
multibyte string into a wide character string while at the same time
converting all lowercase characters into uppercase could look like this
(this is not the final version, just an example; it has no error
checking, and sometimes leaks memory):
A function that copies a multibyte string into a wide character string
while at the same time converting all lowercase characters into
uppercase could look like this:
@smallexample
wchar_t *
mbstouwcs (const char *s)
@{
size_t len = strlen (s);
wchar_t *result = malloc ((len + 1) * sizeof (wchar_t));
wchar_t *wcp = result;
wchar_t tmp[1];
mbstate_t state;
size_t nbytes;
memset (&state, '\0', sizeof (state));
while ((nbytes = mbrtowc (tmp, s, len, &state)) > 0)
@{
if (nbytes >= (size_t) -2)
/* Invalid input string. */
return NULL;
*wcp++ = towupper (tmp[0]);
len -= nbytes;
s += nbytes;
@}
return result;
@}
@include mbstouwcs.c.texi
@end smallexample
The use of @code{mbrtowc} should be clear. A single wide character is
stored in @code{@var{tmp}[0]}, and the number of consumed bytes is stored
in the variable @var{nbytes}. If the conversion is successful, the
uppercase variant of the wide character is stored in the @var{result}
array and the pointer to the input string and the number of available
bytes is adjusted.
In the inner loop, a single wide character is stored in @code{wc}, and
the number of consumed bytes is stored in the variable @code{nbytes}.
If the conversion is successful, the uppercase variant of the wide
character is stored in the @code{result} array and the pointer to the
input string and the number of available bytes is adjusted. If the
@code{mbrtowc} function returns zero, the null input byte has not been
converted, so it must be stored explicitly in the result.
The only non-obvious thing about @code{mbrtowc} might be the way memory
is allocated for the result. The above code uses the fact that there
can never be more wide characters in the converted result than there are
bytes in the multibyte input string. This method yields a pessimistic
guess about the size of the result, and if many wide character strings
have to be constructed this way or if the strings are long, the extra
memory required to be allocated because the input string contains
multibyte characters might be significant. The allocated memory block can
be resized to the correct size before returning it, but a better solution
might be to allocate just the right amount of space for the result right
away. Unfortunately there is no function to compute the length of the wide
character string directly from the multibyte string. There is, however, a
function that does part of the work.
The above code uses the fact that there can never be more wide
characters in the converted result than there are bytes in the multibyte
input string. This method yields a pessimistic guess about the size of
the result, and if many wide character strings have to be constructed
this way or if the strings are long, the extra memory required to be
allocated because the input string contains multibyte characters might
be significant. The allocated memory block can be resized to the
correct size before returning it, but a better solution might be to
allocate just the right amount of space for the result right away.
Unfortunately there is no function to compute the length of the wide
character string directly from the multibyte string. There is, however,
a function that does part of the work.
@deftypefun size_t mbrlen (const char *restrict @var{s}, size_t @var{n}, mbstate_t *@var{ps})
@standards{ISO, wchar.h}
+41 -7
View File
@@ -8,7 +8,7 @@ is controlled by which @dfn{feature test macros} you define.
If you compile your programs using @samp{gcc -ansi}, you get only the
@w{ISO C} library features, unless you explicitly request additional
features by defining one or more of the feature macros.
@xref{Invoking GCC,, GNU CC Command Options, gcc.info, The GNU CC Manual},
@xref{Invoking GCC,, GNU CC Command Options, gcc, The GNU CC Manual},
for more information about GCC options.@refill
You should define these macros by using @samp{#define} preprocessor
@@ -61,13 +61,27 @@ If you define this macro to a value greater than or equal to @code{199309L},
then the functionality from the 1993 edition of the POSIX.1b standard
(IEEE Standard 1003.1b-1993) is made available.
If you define this macro to a value greater than or equal to
@code{199506L}, then the functionality from the 1995 edition of the
POSIX.1c standard (IEEE Standard 1003.1c-1995) is made available.
If you define this macro to a value greater than or equal to
@code{200112L}, then the functionality from the 2001 edition of the
POSIX standard (IEEE Standard 1003.1-2001) is made available.
If you define this macro to a value greater than or equal to
@code{200809L}, then the functionality from the 2008 edition of the
POSIX standard (IEEE Standard 1003.1-2008) is made available.
Greater values for @code{_POSIX_C_SOURCE} will enable future extensions.
The POSIX standards process will define these values as necessary, and
@theglibc{} should support them some time after they become standardized.
The 1996 edition of POSIX.1 (ISO/IEC 9945-1: 1996) states that
if you define @code{_POSIX_C_SOURCE} to a value greater than
or equal to @code{199506L}, then the functionality from the 1996
edition is made available.
edition is made available. In general, in @theglibc{}, bugfixes to
the standards are included when specifying the base version; e.g.,
POSIX.1-2004 will always be included with a value of @code{200112L}.
@end defvr
@defvr Macro _XOPEN_SOURCE
@@ -87,7 +101,10 @@ available which are necessary for the X/Open Unix brand.
If the macro @code{_XOPEN_SOURCE} has the value @math{500} this includes
all functionality described so far plus some new definitions from the
Single Unix Specification, @w{version 2}.
Single Unix Specification, @w{version 2}. The value @math{600}
(corresponding to the sixth revision) includes definitions from SUSv3,
and using @math{700} (the seventh revision) includes definitions from
SUSv4.
@end defvr
@defvr Macro _LARGEFILE_SOURCE
@@ -150,10 +167,14 @@ This macro was introduced as part of the Large File Support extension
@defvr Macro _ISOC99_SOURCE
@standards{GNU, (none)}
Until the revised @w{ISO C} standard is widely adopted the new features
are not automatically enabled. @Theglibc{} nevertheless has a complete
implementation of the new standard and to enable the new features the
macro @code{_ISOC99_SOURCE} should be defined.
If this macro is defined, features from ISO C99 are included. Since
these features are included by default, this macro is mostly relevant
when the compiler uses an earlier language version.
@end defvr
@defvr Macro _ISOC11_SOURCE
@standards{C11, (none)}
If this macro is defined, ISO C11 extensions to ISO C99 are included.
@end defvr
@defvr Macro __STDC_WANT_LIB_EXT2__
@@ -209,6 +230,19 @@ enables those features even when the other options would otherwise
cause them to be disabled.
@end defvr
@defvr Macro _ATFILE_SOURCE
@standards{GNU, (none)}
If this macro is defined, additional @code{*at} interfaces are
included.
@end defvr
@defvr Macro _FORTIFY_SOURCE
@standards{GNU, (none)}
If this macro is defined to @math{1}, security hardening is added to
various library functions. If defined to @math{2}, even stricter
checks are applied.
@end defvr
@defvr Macro _REENTRANT
@defvrx Macro _THREAD_SAFE
@standards{Obsolete, (none)}
+53
View File
@@ -0,0 +1,53 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
/* Do not include the above headers in the example.
*/
wchar_t *
mbstouwcs (const char *s)
{
/* Include the null terminator in the conversion. */
size_t len = strlen (s) + 1;
wchar_t *result = reallocarray (NULL, len, sizeof (wchar_t));
if (result == NULL)
return NULL;
wchar_t *wcp = result;
mbstate_t state;
memset (&state, '\0', sizeof (state));
while (true)
{
wchar_t wc;
size_t nbytes = mbrtowc (&wc, s, len, &state);
if (nbytes == 0)
{
/* Terminate the result string. */
*wcp = L'\0';
break;
}
else if (nbytes == (size_t) -2)
{
/* Truncated input string. */
errno = EILSEQ;
free (result);
return NULL;
}
else if (nbytes == (size_t) -1)
{
/* Some other error (including EILSEQ). */
free (result);
return NULL;
}
else
{
/* A character was converted. */
*wcp++ = towupper (wc);
len -= nbytes;
s += nbytes;
}
}
return result;
}
+9 -8
View File
@@ -147,19 +147,20 @@ necessarily enough space to contain the directory name. That is why
this function is deprecated.
@end deftypefn
@vindex PWD
@deftypefun {char *} get_current_dir_name (void)
@standards{GNU, unistd.h}
@safety{@prelim{}@mtsafe{@mtsenv{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}}
@c Besides getcwd, which this function calls as a fallback, it calls
@c getenv, with the potential thread-safety issues that brings about.
@vindex PWD
This @code{get_current_dir_name} function is basically equivalent to
@w{@code{getcwd (NULL, 0)}}. The only difference is that the value of
the @code{PWD} variable is returned if this value is correct. This is a
subtle difference which is visible if the path described by the
@code{PWD} value is using one or more symbol links in which case the
value returned by @code{getcwd} can resolve the symbol links and
therefore yield a different result.
The @code{get_current_dir_name} function is basically equivalent to
@w{@code{getcwd (NULL, 0)}}, except the value of the @env{PWD}
environment variable is first examined, and if it does in fact
correspond to the current directory, that value is returned. This is
a subtle difference which is visible if the path described by the
value in @env{PWD} is using one or more symbolic links, in which case
the value returned by @code{getcwd} would resolve the symbolic links
and therefore yield a different result.
This function is a GNU extension.
@end deftypefun
+22 -12
View File
@@ -1251,9 +1251,13 @@ When the source file is compiled using @code{_FILE_OFFSET_BITS == 64} on a
@c This is a syscall for Linux v4.6. The sysdeps/posix fallback emulation
@c is also MT-Safe since it calls preadv.
This function is similar to the @code{preadv} function, with the difference
it adds an extra @var{flags} parameter of type @code{int}. The supported
@var{flags} are dependent of the underlying system. For Linux it supports:
This function is similar to the @code{preadv} function, with the
difference it adds an extra @var{flags} parameter of type @code{int}.
Additionally, if @var{offset} is @math{-1}, the current file position
is used and updated (like the @code{readv} function).
The supported @var{flags} are dependent of the underlying system. For
Linux it supports:
@vtable @code
@item RWF_HIPRI
@@ -1271,6 +1275,9 @@ Per-IO synchronization as if the file was opened with @code{O_SYNC} flag.
@item RWF_NOWAIT
Use nonblocking mode for this operation; that is, this call to @code{preadv2}
will fail and set @code{errno} to @code{EAGAIN} if the operation would block.
@item RWF_APPEND
Per-IO synchronization as if the file was opened with @code{O_APPEND} flag.
@end vtable
When the source file is compiled with @code{_FILE_OFFSET_BITS == 64} the
@@ -1320,10 +1327,13 @@ When the source file is compiled using @code{_FILE_OFFSET_BITS == 64} on a
@c This is a syscall for Linux v4.6. The sysdeps/posix fallback emulation
@c is also MT-Safe since it calls pwritev.
This function is similar to the @code{pwritev} function, with the difference
it adds an extra @var{flags} parameter of type @code{int}. The supported
@var{flags} are dependent of the underlying system and for Linux it supports
the same ones as for @code{preadv2}.
This function is similar to the @code{pwritev} function, with the
difference it adds an extra @var{flags} parameter of type @code{int}.
Additionally, if @var{offset} is @math{-1}, the current file position
should is used and updated (like the @code{writev} function).
The supported @var{flags} are dependent of the underlying system. For
Linux, the supported flags are the same as those for @code{preadv2}.
When the source file is compiled with @code{_FILE_OFFSET_BITS == 64} the
@code{pwritev2} function is in fact @code{pwritev64v2} and the type
@@ -1394,10 +1404,13 @@ failure occurs. The return value is zero if the end of the input file
is encountered immediately.
If no bytes can be copied, to report an error, @code{copy_file_range}
returns the value @math{-1} and sets @code{errno}. The following
@code{errno} error conditions are specific to this function:
returns the value @math{-1} and sets @code{errno}. The table below
lists some of the error conditions for this function.
@table @code
@item ENOSYS
The kernel does not implement the required functionality.
@item EISDIR
At least one of the descriptors @var{inputfd} or @var{outputfd} refers
to a directory.
@@ -1427,9 +1440,6 @@ reading.
The argument @var{outputfd} is not a valid file descriptor open for
writing, or @var{outputfd} has been opened with @code{O_APPEND}.
@item EXDEV
The input and output files reside on different file systems.
@end table
In addition, @code{copy_file_range} can fail with the error codes
+1 -1
View File
@@ -123,7 +123,7 @@ when it is not allowed, the priority is set to medium.
Cache management facilities specific to RISC-V systems that implement the Linux
ABI are declared in @file{sys/cachectl.h}.
@deftypefun {void} __riscv_flush_icache(void *@var{start}, void *@var{end}, unsigned long int @var{flags})
@deftypefun {void} __riscv_flush_icache (void *@var{start}, void *@var{end}, unsigned long int @var{flags})
@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
Enforce ordering between stores and instruction cache fetches. The range of
addresses over which ordering is enforced is specified by @var{start} and
+12
View File
@@ -243,6 +243,18 @@ This probe is triggered when the
value of this tunable.
@end deftp
@deftp Probe memory_tcache_double_free (void *@var{$arg1}, int @var{$arg2})
This probe is triggered when @code{free} determines that the memory
being freed has probably already been freed, and resides in the
per-thread cache. Note that there is an extremely unlikely chance
that this probe will trigger due to random payload data remaining in
the allocated memory matching the key used to detect double frees.
This probe actually indicates that an expensive linear search of the
tcache, looking for a double free, has happened. Argument @var{$arg1}
is the memory location as passed to @code{free}, Argument @var{$arg2}
is the tcache bin it resides in.
@end deftp
@node Mathematical Function Probes
@section Mathematical Function Probes
+4 -4
View File
@@ -1808,7 +1808,7 @@ verifies that the correct number and types of arguments are supplied.
There is also a GNU C syntax to tell the compiler that a function you
write uses a @code{printf}-style format string.
@xref{Function Attributes, , Declaring Attributes of Functions,
gcc.info, Using GNU CC}, for more information.
gcc, Using GNU CC}, for more information.
@node Table of Output Conversions
@subsection Table of Output Conversions
@@ -2730,7 +2730,7 @@ This tells the compiler that @code{eprintf} uses a format string like
the format string appears as the first argument;
and the arguments to satisfy the format begin with the second.
@xref{Function Attributes, , Declaring Attributes of Functions,
gcc.info, Using GNU CC}, for more information.
gcc, Using GNU CC}, for more information.
@node Parsing a Template String
@subsection Parsing a Template String
@@ -3478,7 +3478,7 @@ verifies that the correct number and types of arguments are supplied.
There is also a GNU C syntax to tell the compiler that a function you
write uses a @code{scanf}-style format string.
@xref{Function Attributes, , Declaring Attributes of Functions,
gcc.info, Using GNU CC}, for more information.
gcc, Using GNU CC}, for more information.
@node Table of Input Conversions
@subsection Table of Input Conversions
@@ -4033,7 +4033,7 @@ know that a function uses a @code{scanf}-style format string. Then it
can check the number and types of arguments in each call to the
function, and warn you when they do not match the format string.
For details, see @ref{Function Attributes, , Declaring Attributes of Functions,
gcc.info, Using GNU CC}.
gcc, Using GNU CC}.
@node EOF and Errors
@section End-Of-File and Errors
+1 -1
View File
@@ -1087,7 +1087,7 @@ are often easier and safer automatic techniques that cause buffer
overruns to reliably terminate a program, such as GCC's
@option{-fcheck-pointer-bounds} and @option{-fsanitize=address}
options. @xref{Debugging Options,, Options for Debugging Your Program
or GCC, gcc.info, Using GCC}. Because truncation functions can mask
or GCC, gcc, Using GCC}. Because truncation functions can mask
application bugs that would otherwise be caught by the automatic
techniques, these functions should be used only when the application's
underlying logic requires truncation.
+3 -3
View File
@@ -188,8 +188,8 @@ per-thread cache. The default (and maximum) value is 1032 bytes on
@deftp Tunable glibc.malloc.tcache_count
The maximum number of chunks of each size to cache. The default is 7.
There is no upper limit, other than available system memory. If set
to zero, the per-thread cache is effectively disabled.
The upper limit is 127. If set to zero, the per-thread cache is effectively
disabled.
The approximate maximum overhead of the per-thread cache is thus equal
to the number of bins times the chunk count in each bin times the size
@@ -333,7 +333,7 @@ This tunable is specific to powerpc, powerpc64 and powerpc64le.
The @code{glibc.tune.cpu=xxx} tunable allows the user to tell @theglibc{} to
assume that the CPU is @code{xxx} where xxx may have one of these values:
@code{generic}, @code{falkor}, @code{thunderxt88}, @code{thunderx2t99},
@code{thunderx2t99p1}.
@code{thunderx2t99p1}, @code{ares}.
This tunable is specific to aarch64.
@end deftp
+1 -1
View File
@@ -1223,7 +1223,7 @@ template<> struct __iseqsig_type<double>
template<> struct __iseqsig_type<long double>
{
static int __call (double __x, double __y) throw ()
static int __call (long double __x, long double __y) throw ()
{
# ifndef __NO_LONG_DOUBLE_MATH
return __iseqsigl (__x, __y);
+38
View File
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <array_length.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
@@ -25,6 +26,7 @@
#include <support/check.h>
#include <support/temp_file.h>
#include <support/xunistd.h>
static char *temp_filename;
static int temp_fd;
@@ -50,6 +52,42 @@ do_prepare (int argc, char **argv)
pwritev (__fd, __iov, __iovcnt, __offset)
#endif
static __attribute__ ((unused)) void
do_test_without_offset (void)
{
xftruncate (temp_fd, 0);
xwrite (temp_fd, "123", 3);
xlseek (temp_fd, 2, SEEK_SET);
{
struct iovec iov[] =
{
{ (void *) "abc", 3 },
{ (void *) "xyzt", 4 },
};
TEST_COMPARE (PWRITEV (temp_fd, iov, array_length (iov), -1), 7);
}
TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 9);
xlseek (temp_fd, 1, SEEK_SET);
char buf1[3];
char buf2[2];
{
struct iovec iov[] =
{
{ buf1, sizeof (buf1) },
{ buf2, sizeof (buf2) },
};
TEST_COMPARE (PREADV (temp_fd, iov, array_length (iov), -1),
sizeof (buf1) + sizeof (buf2));
TEST_COMPARE (memcmp ("2ab", buf1, sizeof (buf1)), 0);
TEST_COMPARE (memcmp ("cx", buf2, sizeof (buf2)), 0);
TEST_COMPARE (xlseek (temp_fd, 0, SEEK_CUR), 6);
}
xftruncate (temp_fd, 0);
}
static int
do_test_with_offset (off_t offset)
{

Some files were not shown because too many files have changed in this diff Show More