mirror of
git://sourceware.org/git/glibc.git
synced 2026-09-09 05:59:27 +08:00
Compare commits
89
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2097879f6e | ||
|
|
d044eb659e | ||
|
|
623bd741fb | ||
|
|
673776c7be | ||
|
|
5ae9c869b0 | ||
|
|
00411d0fad | ||
|
|
8e684b1ddc | ||
|
|
98b2b7be53 | ||
|
|
0a933c9bf7 | ||
|
|
ae54df4654 | ||
|
|
48557d36a0 | ||
|
|
5b97637011 | ||
|
|
b91a135500 | ||
|
|
d3c633b03d | ||
|
|
8175ef182f | ||
|
|
c1ffff3c53 | ||
|
|
9dc7be063e | ||
|
|
ae41adf241 | ||
|
|
9f65638ed1 | ||
|
|
1d60cac326 | ||
|
|
712ff06cd6 | ||
|
|
c1540fcdde | ||
|
|
8d83145f7f | ||
|
|
e5387c9493 | ||
|
|
4c3292f634 | ||
|
|
ebaeeb8112 | ||
|
|
c949920ef6 | ||
|
|
51a2a92502 | ||
|
|
b7c497474b | ||
|
|
258ea84448 | ||
|
|
6deb970376 | ||
|
|
6465987859 | ||
|
|
da2b1f328e | ||
|
|
9ae7611c80 | ||
|
|
180cbc0cc9 | ||
|
|
fed92e28c5 | ||
|
|
967c9fd3eb | ||
|
|
319de14379 | ||
|
|
9b3a4a701d | ||
|
|
612ba930aa | ||
|
|
6a180670f8 | ||
|
|
dc4b8962cb | ||
|
|
4b23aedb1b | ||
|
|
e4b9aa70a7 | ||
|
|
8ee1efc90d | ||
|
|
ba3e3ae80b | ||
|
|
afe9efb47c | ||
|
|
a48d71c81f | ||
|
|
61ad23190e | ||
|
|
8beaca2512 | ||
|
|
5d1b94809c | ||
|
|
766ed38275 | ||
|
|
21d50c555f | ||
|
|
278994710b | ||
|
|
925d03df27 | ||
|
|
11aa5935bc | ||
|
|
c378eb4388 | ||
|
|
ea81e7d8c6 | ||
|
|
eadfcdb2b9 | ||
|
|
b5a09ebb3f | ||
|
|
43ba3b5c3a | ||
|
|
63c5414e81 | ||
|
|
78ddfecdd5 | ||
|
|
beb6d2de65 | ||
|
|
b26c1af4bd | ||
|
|
31bc3437c9 | ||
|
|
d8e83281aa | ||
|
|
2713ad3e90 | ||
|
|
4977d28d6b | ||
|
|
46e4070d56 | ||
|
|
ac05570fcd | ||
|
|
b59c34e8f9 | ||
|
|
541a425162 | ||
|
|
0fd666fb4b | ||
|
|
5197a3a2f7 | ||
|
|
7417fcf25a | ||
|
|
8cc687cbac | ||
|
|
84c6cfb9b6 | ||
|
|
5c94ce98f7 | ||
|
|
dc48df09cd | ||
|
|
d5c20a5be6 | ||
|
|
8e44f1e0b6 | ||
|
|
4c7cf51f83 | ||
|
|
915959c55d | ||
|
|
59d419cf12 | ||
|
|
73c7242778 | ||
|
|
8ab4aa30e5 | ||
|
|
f13e58f9b1 | ||
|
|
aacf6238fb |
@@ -292,6 +292,15 @@ passed to 'configure'. For example:
|
||||
|
||||
Default is to disable fortification.
|
||||
|
||||
'--enable-ubsan'
|
||||
Build the GNU C library with, along with tests, with the
|
||||
-fsanitize=undefined compiler option. The compiler runtime is not
|
||||
used, instead UBSAN functions called by the compiler instrumentation
|
||||
is provided by glibc itself.
|
||||
|
||||
This is a debug/development option and the default is to disable
|
||||
the instrumentation.
|
||||
|
||||
To build the library and related programs, type 'make'. This will
|
||||
produce a lot of output, some of which may look like errors from 'make'
|
||||
but aren't. Look for error messages from 'make' containing '***'.
|
||||
|
||||
+4
-2
@@ -995,12 +995,14 @@ ifeq "$(strip $(+cflags))" ""
|
||||
+cflags := $(default_cflags)
|
||||
endif # $(+cflags) == ""
|
||||
|
||||
+ubsan-flags = $(cflags-enable-ubsan)
|
||||
|
||||
# Force building with -fno-common because hidden_def, compat_symbol
|
||||
# and other constructs do not work for common symbols (and would
|
||||
# otherwise require specifying __attribute__ ((nocommon)) on a
|
||||
# case-by-case basis).
|
||||
+cflags += $(cflags-cpu) $(+gccwarn) $(+merge-constants) $(+math-flags) \
|
||||
$(+stack-protector) -fno-common
|
||||
$(+stack-protector) $(+ubsan-flags) -fno-common
|
||||
+gcc-nowarn := -w
|
||||
|
||||
# We must filter out elf because the early bootstrap of the dynamic loader
|
||||
@@ -1046,7 +1048,7 @@ libio-include = -I$(..)libio
|
||||
built-modules = iconvprogs iconvdata ldconfig libmemusage \
|
||||
libpcprofile librpcsvc locale-programs \
|
||||
memusagestat nonlib nscd extramodules libnldbl libsupport \
|
||||
testsuite testsuite-internal
|
||||
testsuite testsuite-internal libubsan
|
||||
|
||||
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
|
||||
$(libof-$(<F)) \
|
||||
|
||||
+9
-6
@@ -735,12 +735,15 @@ parser_parse_opt (struct parser *parser, int opt, char *val)
|
||||
}
|
||||
}
|
||||
else
|
||||
/* A long option. We use shifts instead of masking for extracting
|
||||
the user value in order to preserve the sign. */
|
||||
err =
|
||||
group_parse (&parser->groups[group_key - 1], &parser->state,
|
||||
(opt << GROUP_BITS) >> GROUP_BITS,
|
||||
parser->opt_data.optarg);
|
||||
/* A long option. Preserve the sign in the user key, without
|
||||
invoking undefined behavior. Assume two's complement. */
|
||||
{
|
||||
int user_key =
|
||||
((opt & (1 << (USER_BITS - 1))) ? ~USER_MASK : 0) | (opt & USER_MASK);
|
||||
err =
|
||||
group_parse (&parser->groups[group_key - 1], &parser->state,
|
||||
user_key, parser->opt_data.optarg);
|
||||
}
|
||||
|
||||
if (err == EBADKEY)
|
||||
/* At least currently, an option not recognized is an error in the
|
||||
|
||||
@@ -227,6 +227,9 @@
|
||||
/* An integer used to scale the timeout of test programs. */
|
||||
#define TIMEOUTFACTOR 1
|
||||
|
||||
/* Define if glibc should be build with -fsanitize=undefined. */
|
||||
#undef ENABLE_UBSAN
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
|
||||
@@ -701,6 +701,8 @@ INSTALL_DATA
|
||||
INSTALL_SCRIPT
|
||||
INSTALL_PROGRAM
|
||||
base_machine
|
||||
cflags_disable_ubsan
|
||||
cflags_enable_ubsan
|
||||
build_pt_chown
|
||||
build_nscd
|
||||
memory_tagging
|
||||
@@ -820,6 +822,7 @@ enable_mathvec
|
||||
enable_cet
|
||||
enable_scv
|
||||
enable_fortify_source
|
||||
enable_ubsan
|
||||
with_cpu
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
@@ -1505,6 +1508,7 @@ Optional Features:
|
||||
Use -D_FORTIFY_SOURCE=[1|2|3] to control code
|
||||
hardening, defaults to highest possible value
|
||||
supported by the build compiler.
|
||||
--enable-ubsan Build glibc with -fsanitize=undefined
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
@@ -4883,6 +4887,32 @@ case "$enable_fortify_source" in
|
||||
*) as_fn_error $? "Not a valid argument for --enable-fortify-source: \"$enable_fortify_source\"" "$LINENO" 5;;
|
||||
esac
|
||||
|
||||
cflags_enable_ubsan=
|
||||
cflags_disable_ubsan=
|
||||
# Check whether --enable-ubsan was given.
|
||||
if test ${enable_ubsan+y}
|
||||
then :
|
||||
enableval=$enable_ubsan; enable_ubsan=$enableval
|
||||
else case e in #(
|
||||
e) enable_ubsan=no ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
config_vars="$config_vars
|
||||
enable-ubsan = $enable_ubsan"
|
||||
if test "$enable_ubsan" = yes; then
|
||||
printf "%s\n" "#define ENABLE_UBSAN 1" >>confdefs.h
|
||||
|
||||
cflags_enable_ubsan="-fsanitize=undefined"
|
||||
cflags_disable_ubsan="-fno-sanitize=undefined"
|
||||
fi
|
||||
|
||||
|
||||
config_vars="$config_vars
|
||||
cflags-enable-ubsan = $cflags_enable_ubsan"
|
||||
config_vars="$config_vars
|
||||
cflags-disable-ubsan = $cflags_disable_ubsan"
|
||||
|
||||
# We keep the original values in `$config_*' and never modify them, so we
|
||||
# can write them unchanged into config.make. Everything else uses
|
||||
# $machine, $vendor, and $os, and changes them whenever convenient.
|
||||
|
||||
@@ -440,6 +440,24 @@ case "$enable_fortify_source" in
|
||||
*) AC_MSG_ERROR([Not a valid argument for --enable-fortify-source: "$enable_fortify_source"]);;
|
||||
esac
|
||||
|
||||
cflags_enable_ubsan=
|
||||
cflags_disable_ubsan=
|
||||
AC_ARG_ENABLE(ubsan,
|
||||
AS_HELP_STRING([--enable-ubsan],
|
||||
[Build glibc with -fsanitize=undefined]),
|
||||
[enable_ubsan=$enableval],
|
||||
[enable_ubsan=no])
|
||||
LIBC_CONFIG_VAR([enable-ubsan], [$enable_ubsan])
|
||||
if test "$enable_ubsan" = yes; then
|
||||
AC_DEFINE(ENABLE_UBSAN)
|
||||
cflags_enable_ubsan="-fsanitize=undefined"
|
||||
cflags_disable_ubsan="-fno-sanitize=undefined"
|
||||
fi
|
||||
AC_SUBST(cflags_enable_ubsan)
|
||||
AC_SUBST(cflags_disable_ubsan)
|
||||
LIBC_CONFIG_VAR([cflags-enable-ubsan], [$cflags_enable_ubsan])
|
||||
LIBC_CONFIG_VAR([cflags-disable-ubsan], [$cflags_disable_ubsan])
|
||||
|
||||
# We keep the original values in `$config_*' and never modify them, so we
|
||||
# can write them unchanged into config.make. Everything else uses
|
||||
# $machine, $vendor, and $os, and changes them whenever convenient.
|
||||
|
||||
+30
-2
@@ -48,9 +48,35 @@ routines = \
|
||||
rtld_static_init \
|
||||
# routines
|
||||
|
||||
ifeq (yes,$(enable-ubsan))
|
||||
ubsan-routines = \
|
||||
ubsan_error \
|
||||
ubsan_handle_add_overflow \
|
||||
ubsan_handle_builtin_unreachable \
|
||||
ubsan_handle_divrem_overflow \
|
||||
ubsan_handle_dynamic_type_cache_miss \
|
||||
ubsan_handle_invalid_builtin \
|
||||
ubsan_handle_load_invalid_value \
|
||||
ubsan_handle_mul_overflow \
|
||||
ubsan_handle_negate_overflow \
|
||||
ubsan_handle_nonnull_arg \
|
||||
ubsan_handle_nonnull_return_v1 \
|
||||
ubsan_handle_out_of_bounds \
|
||||
ubsan_handle_overflow \
|
||||
ubsan_handle_pointer_overflow \
|
||||
ubsan_handle_shift_out_of_bounds \
|
||||
ubsan_handle_sub_overflow \
|
||||
ubsan_handle_type_mismatch_v1 \
|
||||
ubsan_handle_vla_bound_not_positive \
|
||||
ubsan_val_to_string \
|
||||
ubsan_vptr_type_cache \
|
||||
# ubsan-routines
|
||||
endif
|
||||
|
||||
# The core dynamic linking functions are in libc for the static and
|
||||
# profiled libraries.
|
||||
dl-routines = \
|
||||
$(ubsan-routines) \
|
||||
dl-call-libc-early-init \
|
||||
dl-call_fini \
|
||||
dl-catch \
|
||||
@@ -102,6 +128,8 @@ ifeq (yes,$(have-loop-to-function))
|
||||
CFLAGS-dl-tunables.c += -fno-tree-loop-distribute-patterns
|
||||
endif
|
||||
|
||||
CFLAGS-ubsan_handle_builtin_unreachable.c += -fno-builtin
|
||||
|
||||
all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
|
||||
# But they are absent from the shared libc, because that code is in ld.so.
|
||||
elide-routines.os = \
|
||||
@@ -160,7 +188,7 @@ CFLAGS-dl-minimal-malloc.op = $(no-stack-protector)
|
||||
# On targets without __builtin_memset, rtld.c uses a hand-coded loop
|
||||
# in _dl_start. Make sure this isn't turned into a call to regular memset.
|
||||
ifeq (yes,$(have-loop-to-function))
|
||||
CFLAGS-rtld.c += -fno-tree-loop-distribute-patterns
|
||||
CFLAGS-rtld.c += -fno-tree-loop-distribute-patterns $(cflags-disable-ubsan)
|
||||
endif
|
||||
|
||||
# Compile rtld itself without stack protection.
|
||||
@@ -3434,7 +3462,7 @@ endif
|
||||
# ld.so. The test is always run directly, not under the dynamic
|
||||
# linker. It is necessary to minimize run-time dependencies, by
|
||||
# disabling stack protection and unwinding.
|
||||
CFLAGS-tst-nolink-libc.c += $(no-stack-protector) \
|
||||
CFLAGS-tst-nolink-libc.c += $(no-stack-protector) $(cflags-disable-ubsan) \
|
||||
-fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables
|
||||
$(objpfx)tst-nolink-libc-1: $(objpfx)tst-nolink-libc.o $(objpfx)ld.so
|
||||
$(LINK.o) -nostdlib -nostartfiles -o $@ $< \
|
||||
|
||||
@@ -79,5 +79,24 @@ ld {
|
||||
# Set value of a tunable.
|
||||
__tunable_is_initialized;
|
||||
__tunable_get_val;
|
||||
|
||||
# -fsanitize=undefined support
|
||||
__ubsan_handle_add_overflow;
|
||||
__ubsan_handle_builtin_unreachable;
|
||||
__ubsan_handle_divrem_overflow;
|
||||
__ubsan_handle_dynamic_type_cache_miss;
|
||||
__ubsan_handle_invalid_builtin;
|
||||
__ubsan_handle_load_invalid_value;
|
||||
__ubsan_handle_mul_overflow;
|
||||
__ubsan_handle_negate_overflow;
|
||||
__ubsan_handle_nonnull_arg;
|
||||
__ubsan_handle_nonnull_return_v1;
|
||||
__ubsan_handle_out_of_bounds;
|
||||
__ubsan_handle_pointer_overflow;
|
||||
__ubsan_handle_shift_out_of_bounds;
|
||||
__ubsan_handle_sub_overflow;
|
||||
__ubsan_handle_type_mismatch_v1;
|
||||
__ubsan_handle_vla_bound_not_positive;
|
||||
__ubsan_vptr_type_cache;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1340,7 +1340,7 @@ cannot enable executable stack as shared object requires");
|
||||
|
||||
/* Adjust the address of the TLS initialization image. */
|
||||
if (l->l_tls_initimage != NULL)
|
||||
l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
|
||||
l->l_tls_initimage = (void*)((uintptr_t)l->l_tls_initimage + l->l_addr);
|
||||
|
||||
/* Process program headers again after load segments are mapped in
|
||||
case processing requires accessing those segments. Scan program
|
||||
|
||||
@@ -269,6 +269,12 @@ _dl_debug_printf_c (const char *fmt, ...)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_dl_debug_vprintf_c (const char *fmt, va_list ap)
|
||||
{
|
||||
_dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, ap);
|
||||
}
|
||||
|
||||
/* Write the given file descriptor. */
|
||||
void
|
||||
_dl_dprintf (int fd, const char *fmt, ...)
|
||||
|
||||
@@ -177,4 +177,13 @@ glibc {
|
||||
default: 1048576
|
||||
}
|
||||
}
|
||||
|
||||
ubsan {
|
||||
halt_on_errors {
|
||||
type: INT_32
|
||||
minval: 0
|
||||
maxval: 1
|
||||
default: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -995,7 +995,7 @@ typedef struct
|
||||
range. Be compatible. */
|
||||
#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
|
||||
#define DT_FILTER 0x7fffffff /* Shared object to get values from */
|
||||
#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
|
||||
#define DT_EXTRATAGIDX(tag) (-((Elf32_Sword)((Elf32_Word)(tag) * 2) / 2 + 1))
|
||||
#define DT_EXTRANUM 3
|
||||
|
||||
/* Values of `d_un.d_val' in the DT_FLAGS entry. */
|
||||
|
||||
@@ -24,6 +24,18 @@
|
||||
|
||||
extern int _dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr);
|
||||
|
||||
#ifdef ENABLE_UBSAN
|
||||
void __GI___ubsan_handle_pointer_overflow (void *d, void *v, void *r)
|
||||
{
|
||||
return __ubsan_handle_pointer_overflow (d, v, r);
|
||||
}
|
||||
|
||||
void __GI___ubsan_handle_type_mismatch_v1 (void *d, void *p)
|
||||
{
|
||||
return __ubsan_handle_type_mismatch_v1 (d, p);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ldsodefs.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <abort-instr.h>
|
||||
#include <ubsan.h>
|
||||
#include <dl-tunables.h>
|
||||
|
||||
static void _Noreturn
|
||||
ubsan_abort (void)
|
||||
{
|
||||
/* abort() pulls a lot of extra definition from libc (rwlock, signal
|
||||
hanlding, pthread, etc.; so use a more simpler implementation for
|
||||
now. */
|
||||
raise (SIGABRT);
|
||||
|
||||
#ifdef ABORT_INSTRUCTION
|
||||
ABORT_INSTRUCTION;
|
||||
#endif
|
||||
_exit (127);
|
||||
}
|
||||
|
||||
void
|
||||
__ubsan_error (const struct source_location *source,
|
||||
const char *fmt,
|
||||
...)
|
||||
{
|
||||
_dl_debug_printf_c ("UBSAN: Undefined behaviour in %s:%u:%u ",
|
||||
get_source_location_file_name (source),
|
||||
get_source_location_line (source),
|
||||
get_source_location_column (source));
|
||||
|
||||
va_list ap;
|
||||
va_start (ap, fmt);
|
||||
_dl_debug_vprintf_c (fmt, ap);
|
||||
va_end (ap);
|
||||
|
||||
if (TUNABLE_GET (glibc, ubsan, halt_on_errors, int32_t, NULL))
|
||||
ubsan_abort ();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_add_overflow (void *_data, void *lhs, void *rhs)
|
||||
{
|
||||
__ubsan_handle_overflow (_data, lhs, rhs, "+");
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_add_overflow)
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_builtin_unreachable (void *_data)
|
||||
{
|
||||
struct unreachable_data *data = _data;
|
||||
__ubsan_error (&data->location, "calling __builtin_unreachable()\n");
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_builtin_unreachable)
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs)
|
||||
{
|
||||
struct overflow_data *data = _data;
|
||||
char lhs_str[UBSAN_VAL_STR_LEN];
|
||||
char rhs_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (lhs_str, data->type, lhs);
|
||||
__ubsan_val_to_string (rhs_str, data->type, rhs);
|
||||
|
||||
if (ubsan_type_is_signed (data->type)
|
||||
&& ubsan_get_signed_val (data->type, rhs))
|
||||
__ubsan_error (&data->location,
|
||||
"division overflow: division of %s by -1 cannot be "
|
||||
"represented in type %s\n",
|
||||
rhs_str, data->type->type_name);
|
||||
else
|
||||
__ubsan_error (&data->location, "division by zero");
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_divrem_overflow)
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
|
||||
void
|
||||
__ubsan_handle_dynamic_type_cache_miss (void *_data, void *pointer, void *hash)
|
||||
{
|
||||
/* TODO: this failure requires additional check to check for real
|
||||
issues. Ignore for now. */
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_dynamic_type_cache_miss)
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_invalid_builtin (void *_data)
|
||||
{
|
||||
struct invalid_builtin_data *data = _data;
|
||||
switch (data->kind)
|
||||
{
|
||||
case ubsan_builtin_check_kind_assume_passed_false:
|
||||
__ubsan_error (&data->location,
|
||||
"assumption is violated during execution\n");
|
||||
break;
|
||||
default:
|
||||
__ubsan_error (&data->location,
|
||||
"passing zero to __builtin_%s()\n",
|
||||
data->kind == ubsan_builtin_check_kind_ctz_passed_zero
|
||||
? "ctz" : "clz");
|
||||
break;
|
||||
}
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_invalid_builtin)
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_load_invalid_value (void *_data, void *val)
|
||||
{
|
||||
struct invalid_value_data *data = _data;
|
||||
char val_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (val_str, data->type, val);
|
||||
__ubsan_error (&data->location,
|
||||
"load of value %s is not a valid value for type %s\n",
|
||||
val_str,
|
||||
data->type->type_name);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_load_invalid_value)
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_mul_overflow (void *_data, void *lhs, void *rhs)
|
||||
{
|
||||
__ubsan_handle_overflow (_data, lhs, rhs, "*");
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_mul_overflow)
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_negate_overflow (void *_data, void *val)
|
||||
{
|
||||
struct overflow_data *data = _data;
|
||||
char val_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string(val_str, data->type, val);
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"negation of %s cannot be represented in type %s\n",
|
||||
val_str,
|
||||
data->type->type_name);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_negate_overflow)
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_nonnull_arg (void *_data)
|
||||
{
|
||||
struct nonnull_arg_data *data = _data;
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"null pointer passed as argument %u, nonnull attribute "
|
||||
"declared at %s:%u:%u\n",
|
||||
data->arg_index,
|
||||
get_source_location_file_name (&data->attr_location),
|
||||
get_source_location_line (&data->attr_location),
|
||||
get_source_location_column (&data->attr_location));
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_nonnull_arg)
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_nonnull_return_v1 (void *_data, void *_location)
|
||||
{
|
||||
struct nonnull_return_data *data = _data;
|
||||
struct source_location *location = _location;
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"null pointer returned from function declared as "
|
||||
"returns_nonnull: source %s:%u:%u\n",
|
||||
get_source_location_file_name (location),
|
||||
get_source_location_line (location),
|
||||
get_source_location_column (location));
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_nonnull_return_v1)
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_out_of_bounds (void *_data, void *index)
|
||||
{
|
||||
struct out_of_bounds_data *data = _data;
|
||||
char index_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (index_str, data->index_type, index);
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"index %s is out of bounds for type %s\n",
|
||||
index_str,
|
||||
data->array_type->type_name);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_out_of_bounds)
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 "ubsan.h"
|
||||
|
||||
void
|
||||
__ubsan_handle_overflow (const struct overflow_data * data, void *lhs,
|
||||
void *rhs, const char *op)
|
||||
{
|
||||
char lhs_str[UBSAN_VAL_STR_LEN];
|
||||
char rhs_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (lhs_str, data->type, lhs);
|
||||
__ubsan_val_to_string (rhs_str, data->type, rhs);
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"%s integer overflow: %s %s %s cannot be represened in "
|
||||
"type %s\n",
|
||||
ubsan_type_is_signed (data->type) ? "signed" : "unsigned",
|
||||
lhs_str,
|
||||
op,
|
||||
rhs_str,
|
||||
data->type->type_name);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <stddef.h>
|
||||
#include <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_pointer_overflow (void *_data, void *val, void *result)
|
||||
{
|
||||
struct pointer_overflow_data *data = _data;
|
||||
|
||||
if (val == NULL && result == NULL)
|
||||
__ubsan_error (&data->location,
|
||||
"applying zero offset to a NULL pointer\n");
|
||||
else if (val == NULL && result != NULL)
|
||||
__ubsan_error (&data->location,
|
||||
"applying non-zero offset to a NULL pointer\n");
|
||||
else if (val != NULL && result == NULL)
|
||||
__ubsan_error (&data->location,
|
||||
"applying non-zero offset to non-NULL pointer 0x%0*lx "
|
||||
"produced NULL pointer\n",
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) val);
|
||||
else if (((intptr_t)val >= 0) == ((intptr_t)result >= 0))
|
||||
{
|
||||
const char *operation = ((uintptr_t)val > (uintptr_t)result)
|
||||
? "addition" : "subtraction";
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"%s of unsigned offset to 0x%0*lx overflowed "
|
||||
"to 0x%0*lx\n",
|
||||
operation,
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) val,
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) result);
|
||||
}
|
||||
else
|
||||
__ubsan_error (&data->location,
|
||||
"pointer index expression with base 0x%0*lx overflowed "
|
||||
"to 0x%0*lx\n",
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) val,
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) result);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_pointer_overflow)
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs)
|
||||
{
|
||||
struct shift_out_of_bounds_data *data = _data;
|
||||
char lhs_str[UBSAN_VAL_STR_LEN];
|
||||
char rhs_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (lhs_str, data->lhs_type, lhs);
|
||||
__ubsan_val_to_string (rhs_str, data->rhs_type, rhs);
|
||||
|
||||
if (ubsan_val_is_negative (data->rhs_type, rhs))
|
||||
__ubsan_error (&data->location,
|
||||
"shift expoenent %s is negative\n",
|
||||
rhs_str);
|
||||
else if (ubsan_get_unsigned_val (data->rhs_type, rhs) >=
|
||||
ubsan_type_bit_width (data->lhs_type))
|
||||
__ubsan_error (&data->location,
|
||||
"shift exponent %s is too large for %u-bit type %s\n",
|
||||
rhs_str,
|
||||
ubsan_type_bit_width (data->lhs_type),
|
||||
data->lhs_type->type_name);
|
||||
else if (ubsan_val_is_negative (data->lhs_type, lhs))
|
||||
__ubsan_error (&data->location,
|
||||
"left shift of negative valor %s\n",
|
||||
lhs_str);
|
||||
else
|
||||
__ubsan_error (&data->location,
|
||||
"left shift of %s by %s cannot be represented in type %s\n",
|
||||
lhs_str,
|
||||
rhs_str,
|
||||
data->lhs_type->type_name);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_shift_out_of_bounds)
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_sub_overflow (void *_data, void *lhs, void *rhs)
|
||||
{
|
||||
__ubsan_handle_overflow (_data, lhs, rhs, "-");
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_sub_overflow)
|
||||
@@ -0,0 +1,75 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
static const char *
|
||||
type_check_to_string (unsigned char type_check_kind)
|
||||
{
|
||||
switch (type_check_kind)
|
||||
{
|
||||
case ubsan_type_check_load: return "load of";
|
||||
case ubsan_type_check_store: return "store to";
|
||||
case ubsan_type_check_reference_binding: return "reference binding to";
|
||||
case ubsan_type_check_member_access: return "member access within";
|
||||
case ubsan_type_check_member_call: return "member call on";
|
||||
case ubsan_type_check_constructor_call: return "constructor call on";
|
||||
case ubsan_type_check_downcast_pointer:
|
||||
case ubsan_type_check_downcast_reference: return "downcast of";
|
||||
case ubsan_type_check_upcast: return "upcast of";
|
||||
case ubsan_type_check_upcast_to_virtual_base: return "cast to virtual base of";
|
||||
case ubsan_type_check_nonnull_assign: return "_Nonnull binding to";
|
||||
case ubsan_type_check_dynamic_operation: return "dynamic operation on";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_misaligned_pointer (const struct type_mismatch_data_v1 *data, void *ptr)
|
||||
{
|
||||
uintptr_t alignment = 1UL << data->log_alignment;
|
||||
return (uintptr_t) ptr & (alignment - 1);
|
||||
}
|
||||
|
||||
void
|
||||
__ubsan_handle_type_mismatch_v1 (void *_data, void *ptr)
|
||||
{
|
||||
struct type_mismatch_data_v1 *data = _data;
|
||||
|
||||
if (data->type_check_kind == ubsan_type_check_nonnull_assign)
|
||||
__ubsan_error (&data->location,
|
||||
"%s null pointer of type %s\n",
|
||||
type_check_to_string (data->type_check_kind),
|
||||
data->type->type_name);
|
||||
else if (is_misaligned_pointer (data, ptr))
|
||||
__ubsan_error (&data->location,
|
||||
"%s misaligned address 0x%0*lx for type %s\n",
|
||||
type_check_to_string (data->type_check_kind),
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) ptr,
|
||||
data->type->type_name);
|
||||
else
|
||||
__ubsan_error (&data->location,
|
||||
"%s address 0x%0*lx with insufficient space for an "
|
||||
"object of type %s\n",
|
||||
type_check_to_string (data->type_check_kind),
|
||||
(int) sizeof (void *) * 2,
|
||||
(unsigned long int) ptr,
|
||||
data->type->type_name);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_type_mismatch_v1)
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
void
|
||||
__ubsan_handle_vla_bound_not_positive (void *_data, void *bound)
|
||||
{
|
||||
struct vla_bound_not_positive_data *data = _data;
|
||||
char bound_str[UBSAN_VAL_STR_LEN];
|
||||
|
||||
__ubsan_val_to_string (bound_str, data->type, bound);
|
||||
|
||||
__ubsan_error (&data->location,
|
||||
"variable length array bound evaluates to "
|
||||
"non-positive value %s\n",
|
||||
bound_str);
|
||||
}
|
||||
rtld_hidden_def (__ubsan_handle_vla_bound_not_positive)
|
||||
@@ -0,0 +1,189 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <intprops.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ubsan.h"
|
||||
|
||||
static const char lower_digits[] = "0123456789";
|
||||
|
||||
enum { BASE = 10 };
|
||||
|
||||
static char *
|
||||
utoa (unsigned long long int value, char *buf, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return buf;
|
||||
|
||||
char *ptr = buf;
|
||||
do
|
||||
{
|
||||
if (len-- == 0)
|
||||
break;
|
||||
*ptr++ = lower_digits[value % BASE];
|
||||
value /= BASE;
|
||||
}
|
||||
while (value != 0);
|
||||
char *r = ptr;
|
||||
*ptr-- = '\0';
|
||||
|
||||
while (buf < ptr)
|
||||
{
|
||||
char t = *ptr;
|
||||
*ptr-- = *buf;
|
||||
*buf++ = t;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *
|
||||
itoa (long long int value, char *buf, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return buf;
|
||||
|
||||
bool isneg = value < 0;
|
||||
char *ptr = buf;
|
||||
do
|
||||
{
|
||||
if (len-- == 0)
|
||||
break;
|
||||
*ptr++ = lower_digits[abs (value % BASE)];
|
||||
value /= BASE;
|
||||
}
|
||||
while (value != 0);
|
||||
if (isneg)
|
||||
*ptr++ = '-';
|
||||
char *r = ptr;
|
||||
*ptr-- = '\0';
|
||||
|
||||
while (buf < ptr)
|
||||
{
|
||||
char t = *ptr;
|
||||
*ptr-- = *buf;
|
||||
*buf++ = t;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static long long int
|
||||
ubsan_val_to_ll (int width, void *value, long long int def)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case 8:
|
||||
return (int8_t) (intptr_t) value;
|
||||
case 16:
|
||||
return (int16_t) (intptr_t) value;
|
||||
case 32:
|
||||
if (sizeof (value) >= sizeof (int32_t))
|
||||
return (int32_t) (intptr_t) value;
|
||||
else
|
||||
return *(int32_t *) value;
|
||||
case 64:
|
||||
if (sizeof (value) >= sizeof (int64_t))
|
||||
return (int64_t) (intptr_t) value;
|
||||
else
|
||||
return *(int64_t *) value;
|
||||
default:
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long long int
|
||||
ubsan_val_to_ull (int width, void *value, unsigned long long int def)
|
||||
{
|
||||
switch (width)
|
||||
{
|
||||
case 8:
|
||||
return (uint8_t) (uintptr_t) value;
|
||||
case 16:
|
||||
return (uint16_t) (uintptr_t) value;
|
||||
case 32:
|
||||
if (sizeof (value) >= sizeof (uint32_t))
|
||||
return (uint32_t) (uintptr_t) value;
|
||||
else
|
||||
return *(uint32_t *) value;
|
||||
case 64:
|
||||
if (sizeof (value) >= sizeof (uint64_t))
|
||||
return (uint64_t) (uintptr_t) value;
|
||||
else
|
||||
return *(uint64_t *) value;
|
||||
default:
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *
|
||||
add_string (char *str, const char *s, size_t *len)
|
||||
{
|
||||
char *endp = __stpncpy (str, s, *len);
|
||||
*len -= endp - str;
|
||||
return endp;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
add_uint (char *str, unsigned long long int value, size_t *len)
|
||||
{
|
||||
char *endp = utoa (value, str, *len);
|
||||
*len -= endp - str;
|
||||
return endp;
|
||||
}
|
||||
|
||||
void
|
||||
__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN],
|
||||
struct type_descriptor *type, void *value)
|
||||
{
|
||||
int width = ubsan_type_bit_width (type);
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case ubsan_type_kind_int:
|
||||
if (ubsan_type_is_signed (type))
|
||||
{
|
||||
long long int v = ubsan_val_to_ll (width, value, 0);
|
||||
itoa (v, str, UBSAN_VAL_STR_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long long int v = ubsan_val_to_ull (width, value, 0);
|
||||
utoa (v, str, UBSAN_VAL_STR_LEN);
|
||||
}
|
||||
break;
|
||||
case ubsan_type_kind_float:
|
||||
{
|
||||
char *endp = __stpcpy (str, "float size ");
|
||||
utoa (width, endp, UBSAN_VAL_STR_LEN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
size_t size = UBSAN_VAL_STR_LEN;
|
||||
char *endp = add_string (str, "kind ", &size);
|
||||
endp = add_uint (endp, type->type_kind, &size);
|
||||
endp = add_string (endp, " (width ", &size);
|
||||
endp = add_uint (endp, width, &size);
|
||||
add_string (endp, " )", &size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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 <ubsan.h>
|
||||
|
||||
unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE];
|
||||
+3
-3
@@ -45,8 +45,8 @@ unsigned int bshort[5][0x100 / sizeof (int)];
|
||||
unsigned int blong[1][0x1000 / sizeof (int)];
|
||||
unsigned int vlong[1][0x2000 / sizeof (int)];
|
||||
|
||||
static long int
|
||||
fac (long int n)
|
||||
static long unsigned int
|
||||
fac (long int unsigned n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 1;
|
||||
@@ -60,7 +60,7 @@ main (int argc, char **argv)
|
||||
struct timeval tv, start;
|
||||
struct prof prof[32];
|
||||
double t_tick, delta;
|
||||
long int sum = 0;
|
||||
long int unsigned sum = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < NELEMS (taddr); ++i)
|
||||
|
||||
+5
-2
@@ -28,6 +28,7 @@
|
||||
#include <dlfcn.h>
|
||||
#include <gconv_int.h>
|
||||
#include <pointer_guard.h>
|
||||
#include <intprops.h>
|
||||
|
||||
|
||||
/* Simple data structure for alias mapping. We have two names, `from'
|
||||
@@ -507,8 +508,10 @@ find_derivation (const char *toset, const char *toset_expand,
|
||||
const char *result_set = (strcmp (runp->to_string, "-") == 0
|
||||
? (toset_expand ?: toset)
|
||||
: runp->to_string);
|
||||
int cost_hi = runp->cost_hi + current->cost_hi;
|
||||
int cost_lo = runp->cost_lo + current->cost_lo;
|
||||
int cost_hi, cost_lo;
|
||||
INT_ADD_WRAPV (runp->cost_hi, current->cost_hi, &cost_hi);
|
||||
INT_ADD_WRAPV (runp->cost_lo, current->cost_lo, &cost_lo);
|
||||
|
||||
struct derivation_step *step;
|
||||
|
||||
/* We managed to find a derivation. First see whether
|
||||
|
||||
+8
-5
@@ -1019,11 +1019,14 @@ write_output (void)
|
||||
/* Open the output file. */
|
||||
if (output_file == NULL)
|
||||
{
|
||||
assert (GCONV_MODULES_CACHE[0] == '/');
|
||||
strcpy (stpcpy (mempcpy (tmpfname, prefix, prefix_len),
|
||||
GCONV_MODULES_CACHE),
|
||||
".XXXXXX");
|
||||
strcpy (mempcpy (finalname, prefix, prefix_len), GCONV_MODULES_CACHE);
|
||||
snprintf (tmpfname, sizeof tmpfname, "%.*s%s.XXXXXX",
|
||||
(int) prefix_len,
|
||||
prefix,
|
||||
GCONV_MODULES_CACHE);
|
||||
snprintf (finalname, sizeof finalname, "%.*s%s",
|
||||
(int) prefix_len,
|
||||
prefix,
|
||||
GCONV_MODULES_CACHE);
|
||||
}
|
||||
else
|
||||
strcpy (mempcpy (tmpfname, output_file, output_file_len), ".XXXXXX");
|
||||
|
||||
@@ -65,5 +65,8 @@ libc_hidden_proto (_libc_intl_domainname)
|
||||
# undef N_
|
||||
# define N_(msgid) msgid
|
||||
|
||||
# undef gettext
|
||||
# define gettext(msgid) (dgettext (NULL, msgid) ?: (char *)msgid)
|
||||
|
||||
# endif /* !_ISOMAC */
|
||||
#endif
|
||||
|
||||
@@ -63,4 +63,10 @@ rtld_hidden_proto (__chk_fail)
|
||||
# define __attribute_optimization_barrier__ __attribute__ ((noinline, noclone))
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_UBSAN
|
||||
# define __attribute_disable_ubsan__ __attribute__((no_sanitize("undefined")))
|
||||
#else
|
||||
# define __attribute_disable_ubsan__
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
/* Undefined Behavior Sanitizer support.
|
||||
Copyright (C) 2025 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/>. */
|
||||
|
||||
#ifndef __UBSAN_H__
|
||||
#define __UBSAN_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <endian.h>
|
||||
|
||||
#ifdef __SIZEOF_INT128__
|
||||
typedef __int128 ubsan_s_max;
|
||||
typedef unsigned __int128 ubsan_u_max;
|
||||
#else
|
||||
typedef int64_t ubsan_u_max;
|
||||
typedef uint64_t ubsan_s_max;
|
||||
#endif
|
||||
|
||||
#define REPORTED_BIT 31
|
||||
#if (__WORDSIZE == 64 && BYTE_ORDER == BIG_ENDIAN)
|
||||
# define COLUMN_MASK (~(1U << REPORTED_BIT))
|
||||
# define LINE_MASK (~0U)
|
||||
#else
|
||||
# define COLUMN_MASK (~0U)
|
||||
# define LINE_MASK (~(1U << REPORTED_BIT))
|
||||
#endif
|
||||
|
||||
struct source_location
|
||||
{
|
||||
const char *file_name;
|
||||
unsigned int line;
|
||||
unsigned int column;
|
||||
};
|
||||
|
||||
static inline const char *
|
||||
get_source_location_file_name (const struct source_location *location)
|
||||
{
|
||||
return location->file_name ? location->file_name : "unknown";
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
get_source_location_line (const struct source_location *location)
|
||||
{
|
||||
return location->line & LINE_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
get_source_location_column (const struct source_location *location)
|
||||
{
|
||||
return location->column & COLUMN_MASK;
|
||||
}
|
||||
|
||||
struct nonnull_arg_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct source_location attr_location;
|
||||
int arg_index;
|
||||
};
|
||||
|
||||
struct type_descriptor
|
||||
{
|
||||
uint16_t type_kind;
|
||||
uint16_t type_info;
|
||||
char type_name[];
|
||||
};
|
||||
|
||||
static inline bool
|
||||
ubsan_type_is_signed (const struct type_descriptor *type)
|
||||
{
|
||||
return type->type_kind & 1;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
ubsan_type_bit_width (const struct type_descriptor *type)
|
||||
{
|
||||
return 1 << (type->type_info >> 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ubsan_is_inline_int (const struct type_descriptor *type)
|
||||
{
|
||||
unsigned int inline_bits = sizeof (unsigned long) * 8;
|
||||
unsigned int bits = ubsan_type_bit_width (type);
|
||||
|
||||
return bits <= inline_bits;
|
||||
}
|
||||
|
||||
static inline ubsan_s_max
|
||||
ubsan_get_signed_val (const struct type_descriptor *type, void *val)
|
||||
{
|
||||
if (ubsan_is_inline_int (type))
|
||||
{
|
||||
unsigned int extra_bits = sizeof (ubsan_s_max) * 8
|
||||
- ubsan_type_bit_width (type);
|
||||
unsigned long ul_val = (unsigned long) val;
|
||||
return ((ubsan_s_max) ul_val) << extra_bits >> extra_bits;
|
||||
}
|
||||
|
||||
if (ubsan_type_bit_width (type) == 64)
|
||||
return *(int64_t*) val;
|
||||
|
||||
return *(ubsan_s_max *) val;
|
||||
}
|
||||
|
||||
static inline ubsan_u_max
|
||||
ubsan_get_unsigned_val (const struct type_descriptor *type, void *val)
|
||||
{
|
||||
if (ubsan_is_inline_int (type))
|
||||
return (unsigned long) val;
|
||||
|
||||
if (ubsan_type_bit_width (type) == 64)
|
||||
return *(uint64_t*) val;
|
||||
|
||||
return *(ubsan_u_max *)val;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ubsan_val_is_negative (const struct type_descriptor *type, void *val)
|
||||
{
|
||||
return ubsan_type_is_signed (type) && ubsan_get_signed_val (type, val) < 0;
|
||||
}
|
||||
|
||||
struct invalid_value_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
/* The type_mismatch_data_v1::type_check_kind */
|
||||
enum
|
||||
{
|
||||
ubsan_type_check_load,
|
||||
ubsan_type_check_store,
|
||||
ubsan_type_check_reference_binding,
|
||||
ubsan_type_check_member_access,
|
||||
ubsan_type_check_member_call,
|
||||
ubsan_type_check_constructor_call,
|
||||
ubsan_type_check_downcast_pointer,
|
||||
ubsan_type_check_downcast_reference,
|
||||
ubsan_type_check_upcast,
|
||||
ubsan_type_check_upcast_to_virtual_base,
|
||||
ubsan_type_check_nonnull_assign,
|
||||
ubsan_type_check_dynamic_operation
|
||||
};
|
||||
|
||||
struct type_mismatch_data_v1
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
unsigned char log_alignment;
|
||||
unsigned char type_check_kind;
|
||||
};
|
||||
|
||||
struct pointer_overflow_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct overflow_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct out_of_bounds_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *array_type;
|
||||
struct type_descriptor *index_type;
|
||||
};
|
||||
|
||||
struct shift_out_of_bounds_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *lhs_type;
|
||||
struct type_descriptor *rhs_type;
|
||||
};
|
||||
|
||||
struct vla_bound_not_positive_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
};
|
||||
|
||||
struct unreachable_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct invalid_builtin_data
|
||||
{
|
||||
struct source_location location;
|
||||
unsigned char kind;
|
||||
};
|
||||
|
||||
struct nonnull_return_data
|
||||
{
|
||||
struct source_location location;
|
||||
};
|
||||
|
||||
struct dynamic_type_cache_miss_data
|
||||
{
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
void *info;
|
||||
unsigned char kind;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ubsan_type_kind_int = 0,
|
||||
ubsan_type_kind_float = 1,
|
||||
ubsan_type_unknown = 0xffff
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ubsan_builtin_check_kind_ctz_passed_zero,
|
||||
ubsan_builtin_check_kind_clz_passed_zero,
|
||||
ubsan_builtin_check_kind_assume_passed_false,
|
||||
};
|
||||
|
||||
#define UBSAN_VAL_STR_LEN 32
|
||||
|
||||
void
|
||||
__ubsan_val_to_string (char str[static UBSAN_VAL_STR_LEN],
|
||||
struct type_descriptor *type, void *value)
|
||||
attribute_hidden;
|
||||
|
||||
#define UBSAN_VPTR_TYPE_CACHE_SIZE 128
|
||||
|
||||
extern unsigned int __ubsan_vptr_type_cache[UBSAN_VPTR_TYPE_CACHE_SIZE];
|
||||
|
||||
#if IS_IN(rtld)
|
||||
# define ubsan_hidden attribute_hidden
|
||||
#else
|
||||
# define ubsan_hidden
|
||||
#endif
|
||||
|
||||
void __ubsan_error (const struct source_location *source,
|
||||
const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 2, 3)))
|
||||
attribute_hidden;
|
||||
|
||||
void __ubsan_handle_overflow (const struct overflow_data *, void *,
|
||||
void *, const char *op)
|
||||
attribute_hidden;
|
||||
|
||||
void __ubsan_handle_load_invalid_value (void *data, void *value)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_load_invalid_value)
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1 (void *data, void *ptr)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_type_mismatch_v1)
|
||||
|
||||
void __ubsan_handle_pointer_overflow (void *data, void *val, void *result)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_pointer_overflow)
|
||||
|
||||
void __ubsan_handle_add_overflow (void *data, void *lhs, void *rhs)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_add_overflow)
|
||||
|
||||
void __ubsan_handle_sub_overflow (void *data, void *lhs, void *rhs)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_sub_overflow)
|
||||
|
||||
void __ubsan_handle_mul_overflow (void *data, void *lhs, void *rhs)
|
||||
attribute_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_mul_overflow)
|
||||
|
||||
void __ubsan_handle_out_of_bounds (void *data, void *index)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_out_of_bounds)
|
||||
|
||||
void __ubsan_handle_negate_overflow (void *data, void *val)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_negate_overflow)
|
||||
|
||||
void __ubsan_handle_shift_out_of_bounds (void *_data, void *lhs, void *rhs)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_shift_out_of_bounds)
|
||||
|
||||
void __ubsan_handle_divrem_overflow (void *_data, void *lhs, void *rhs)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_divrem_overflow)
|
||||
|
||||
void __ubsan_handle_vla_bound_not_positive (void *data, void *bound)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_vla_bound_not_positive)
|
||||
|
||||
void __ubsan_handle_builtin_unreachable (void *data)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_builtin_unreachable)
|
||||
|
||||
void __ubsan_handle_invalid_builtin (void *data)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_invalid_builtin)
|
||||
|
||||
void __ubsan_handle_nonnull_arg (void *data)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_nonnull_arg);
|
||||
|
||||
void __ubsan_handle_nonnull_return_v1 (void *data, void *location)
|
||||
ubsan_hidden;
|
||||
rtld_hidden_proto (__ubsan_handle_nonnull_return_v1)
|
||||
|
||||
void __ubsan_handle_dynamic_type_cache_miss (void *, void *, void *);
|
||||
rtld_hidden_proto (__ubsan_handle_dynamic_type_cache_miss)
|
||||
|
||||
#endif /* __UBSAN_H__ */
|
||||
@@ -228,6 +228,9 @@ __libio_codecvt_length (struct _IO_codecvt *codecvt, __mbstate_t *statep,
|
||||
const char *from_start, const char *from_end,
|
||||
size_t max)
|
||||
{
|
||||
if (max == 0)
|
||||
return 0;
|
||||
|
||||
int result;
|
||||
const unsigned char *cp = (const unsigned char *) from_start;
|
||||
wchar_t to_buf[max];
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ elem_hash (const char *str, int32_t n)
|
||||
|
||||
while (n-- > 0)
|
||||
{
|
||||
result <<= 3;
|
||||
result = (uint32_t)result << 3;
|
||||
result += *str++;
|
||||
}
|
||||
|
||||
|
||||
+40
-34
@@ -212,58 +212,64 @@ static void
|
||||
CONCAT(add_locale_,TABLE) (struct locale_file *file, struct TABLE *t)
|
||||
{
|
||||
size_t i, j, k;
|
||||
uint32_t reorder3[t->level3_size];
|
||||
uint32_t reorder2[t->level2_size];
|
||||
uint32_t level2_offset, level3_offset, last_offset;
|
||||
|
||||
/* Uniquify level3 blocks. */
|
||||
k = 0;
|
||||
for (j = 0; j < t->level3_size; j++)
|
||||
if (t->level3_size > 0)
|
||||
{
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (ELEMENT)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder3[j] = i;
|
||||
if (i == k)
|
||||
uint32_t reorder3[t->level3_size];
|
||||
for (j = 0; j < t->level3_size; j++)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (ELEMENT));
|
||||
k++;
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (ELEMENT)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder3[j] = i;
|
||||
if (i == k)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (ELEMENT));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (t->level2_size << t->q); i++)
|
||||
if (t->level2[i] != EMPTY)
|
||||
t->level2[i] = reorder3[t->level2[i]];
|
||||
}
|
||||
t->level3_size = k;
|
||||
|
||||
for (i = 0; i < (t->level2_size << t->q); i++)
|
||||
if (t->level2[i] != EMPTY)
|
||||
t->level2[i] = reorder3[t->level2[i]];
|
||||
|
||||
/* Uniquify level2 blocks. */
|
||||
k = 0;
|
||||
for (j = 0; j < t->level2_size; j++)
|
||||
if (t->level2_size > 0)
|
||||
{
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder2[j] = i;
|
||||
if (i == k)
|
||||
uint32_t reorder2[t->level2_size];
|
||||
for (j = 0; j < t->level2_size; j++)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t));
|
||||
k++;
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder2[j] = i;
|
||||
if (i == k)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < t->level1_size; i++)
|
||||
if (t->level1[i] != EMPTY)
|
||||
t->level1[i] = reorder2[t->level1[i]];
|
||||
}
|
||||
t->level2_size = k;
|
||||
|
||||
for (i = 0; i < t->level1_size; i++)
|
||||
if (t->level1[i] != EMPTY)
|
||||
t->level1[i] = reorder2[t->level1[i]];
|
||||
|
||||
/* Create and fill the resulting compressed representation. */
|
||||
last_offset =
|
||||
5 * sizeof (uint32_t)
|
||||
|
||||
@@ -904,9 +904,9 @@ number of bytes for byte sequence of beginning and end of range not the same: %d
|
||||
(struct width_rule *) obstack_alloc (&result->mem_pool,
|
||||
(new_size
|
||||
* sizeof (struct width_rule)));
|
||||
|
||||
memcpy (new_rules, result->width_rules,
|
||||
result->nwidth_rules_max * sizeof (struct width_rule));
|
||||
if (result->width_rules != NULL)
|
||||
memcpy (new_rules, result->width_rules,
|
||||
result->nwidth_rules_max * sizeof (struct width_rule));
|
||||
|
||||
result->width_rules = new_rules;
|
||||
result->nwidth_rules_max = new_size;
|
||||
@@ -1014,7 +1014,7 @@ hexadecimal range format should use only capital characters"));
|
||||
|
||||
prefix_len = (cp - from) + 1;
|
||||
|
||||
if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
|
||||
if (check_illegal_range (cp, from, len1, to, prefix_len))
|
||||
goto illegal_range;
|
||||
|
||||
errno = 0;
|
||||
|
||||
@@ -62,6 +62,13 @@ struct charseq
|
||||
unsigned char bytes[];
|
||||
};
|
||||
|
||||
static inline bool
|
||||
__attribute_disable_ubsan__
|
||||
check_illegal_range (const char *cp, const char *from, size_t len1,
|
||||
const char *to, size_t prefix_len)
|
||||
{
|
||||
return cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0;
|
||||
}
|
||||
|
||||
/* True if the encoding is not ASCII compatible. */
|
||||
extern bool enc_not_ascii_compatible;
|
||||
|
||||
@@ -858,7 +858,8 @@ insert_weights (struct linereader *ldfile, struct element_t *elem,
|
||||
max += 10;
|
||||
newp = (struct element_t **)
|
||||
alloca (max * sizeof (struct element_t *));
|
||||
memcpy (newp, weights, cnt * sizeof (struct element_t *));
|
||||
if (weights != NULL)
|
||||
memcpy (newp, weights, cnt * sizeof (struct element_t *));
|
||||
weights = newp;
|
||||
}
|
||||
weights[cnt++] = charelem;
|
||||
@@ -1553,7 +1554,7 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
|
||||
The multibyte case is easy. We simply sort into an array with
|
||||
256 elements. */
|
||||
struct locale_collate_t *collate = locale->categories[LC_COLLATE].collate;
|
||||
int mbact[nrules];
|
||||
int mbact[sizeof (((struct element_t *)0)->used_in_level) * 8];
|
||||
int wcact;
|
||||
int mbseqact;
|
||||
int wcseqact;
|
||||
|
||||
+40
-34
@@ -3423,58 +3423,64 @@ static void
|
||||
add_locale_wctype_table (struct locale_file *file, struct wctype_table *t)
|
||||
{
|
||||
size_t i, j, k;
|
||||
uint32_t reorder3[t->level3_size];
|
||||
uint32_t reorder2[t->level2_size];
|
||||
uint32_t level2_offset, level3_offset;
|
||||
|
||||
/* Uniquify level3 blocks. */
|
||||
k = 0;
|
||||
for (j = 0; j < t->level3_size; j++)
|
||||
if (t->level3_size > 0)
|
||||
{
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder3[j] = i;
|
||||
if (i == k)
|
||||
uint32_t reorder3[t->level3_size];
|
||||
for (j = 0; j < t->level3_size; j++)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (uint32_t));
|
||||
k++;
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder3[j] = i;
|
||||
if (i == k)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level3[i << t->p], &t->level3[j << t->p],
|
||||
(1 << t->p) * sizeof (uint32_t));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < (t->level2_size << t->q); i++)
|
||||
if (t->level2[i] != EMPTY)
|
||||
t->level2[i] = reorder3[t->level2[i]];
|
||||
}
|
||||
t->level3_size = k;
|
||||
|
||||
for (i = 0; i < (t->level2_size << t->q); i++)
|
||||
if (t->level2[i] != EMPTY)
|
||||
t->level2[i] = reorder3[t->level2[i]];
|
||||
|
||||
/* Uniquify level2 blocks. */
|
||||
k = 0;
|
||||
for (j = 0; j < t->level2_size; j++)
|
||||
if (t->level2_size > 0)
|
||||
{
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder2[j] = i;
|
||||
if (i == k)
|
||||
uint32_t reorder2[t->level2_size];
|
||||
for (j = 0; j < t->level2_size; j++)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t));
|
||||
k++;
|
||||
for (i = 0; i < k; i++)
|
||||
if (memcmp (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t)) == 0)
|
||||
break;
|
||||
/* Relocate block j to block i. */
|
||||
reorder2[j] = i;
|
||||
if (i == k)
|
||||
{
|
||||
if (i != j)
|
||||
memcpy (&t->level2[i << t->q], &t->level2[j << t->q],
|
||||
(1 << t->q) * sizeof (uint32_t));
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < t->level1_size; i++)
|
||||
if (t->level1[i] != EMPTY)
|
||||
t->level1[i] = reorder2[t->level1[i]];
|
||||
}
|
||||
t->level2_size = k;
|
||||
|
||||
for (i = 0; i < t->level1_size; i++)
|
||||
if (t->level1[i] != EMPTY)
|
||||
t->level1[i] = reorder2[t->level1[i]];
|
||||
|
||||
t->result_size =
|
||||
5 * sizeof (uint32_t)
|
||||
+ t->level1_size * sizeof (uint32_t)
|
||||
|
||||
@@ -595,6 +595,8 @@ void
|
||||
add_locale_raw_data (struct locale_file *file, const void *data, size_t size)
|
||||
{
|
||||
record_offset (file);
|
||||
if (size == 0)
|
||||
return;
|
||||
obstack_grow (&file->data, data, size);
|
||||
}
|
||||
|
||||
@@ -641,6 +643,8 @@ add_locale_uint32_array (struct locale_file *file,
|
||||
{
|
||||
align_locale_data (file, LOCFILE_ALIGN);
|
||||
record_offset (file);
|
||||
if (n_elems == 0)
|
||||
return;
|
||||
obstack_grow (&file->data, data, n_elems * sizeof (uint32_t));
|
||||
maybe_swap_uint32_obstack (&file->data, n_elems);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,8 @@ extern void end_locale_structure (struct locale_file *file);
|
||||
extern void start_locale_prelude (struct locale_file *file);
|
||||
extern void end_locale_prelude (struct locale_file *file);
|
||||
extern void write_locale_data (const char *output_path, int catidx,
|
||||
const char *category, struct locale_file *file);
|
||||
const char *category, struct locale_file *file)
|
||||
__attribute__ ((nonnull (1, 3, 4)));
|
||||
|
||||
|
||||
/* Entrypoints for the parsers of the individual categories. */
|
||||
|
||||
@@ -433,7 +433,7 @@ hexadecimal range format should use only capital characters"));
|
||||
|
||||
prefix_len = (cp - from) + 1;
|
||||
|
||||
if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
|
||||
if (check_illegal_range (cp, from, len1, to, prefix_len))
|
||||
goto invalid_range;
|
||||
|
||||
errno = 0;
|
||||
|
||||
@@ -202,7 +202,7 @@ __debug_free (void *mem)
|
||||
if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
|
||||
mem = free_mcheck (mem);
|
||||
|
||||
if (DUMPED_MAIN_ARENA_CHUNK (mem2chunk (mem)))
|
||||
if (mem != NULL && DUMPED_MAIN_ARENA_CHUNK (mem2chunk (mem)))
|
||||
/* Do nothing. */;
|
||||
else if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
|
||||
free_check (mem);
|
||||
@@ -227,7 +227,7 @@ __debug_realloc (void *oldmem, size_t bytes)
|
||||
if ((!__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK)
|
||||
|| !realloc_mcheck_before (&oldmem, &bytes, &oldsize, &victim)))
|
||||
{
|
||||
mchunkptr oldp = mem2chunk (oldmem);
|
||||
mchunkptr oldp = oldmem != NULL ? mem2chunk (oldmem) : NULL;
|
||||
|
||||
/* If this is a faked mmapped chunk from the dumped main arena,
|
||||
always make a copy (and do not free the old chunk). */
|
||||
|
||||
@@ -320,6 +320,14 @@ If not provided, @option{LEVEL} defaults to highest possible value supported by
|
||||
the build compiler.
|
||||
|
||||
Default is to disable fortification.
|
||||
|
||||
@item --enable-ubsan
|
||||
Build @theglibc{}, along with tests, with the @code{-fsanitize=undefined}
|
||||
compiler option. The compiler runtime is not used, instead UBSAN functions
|
||||
called by the compiler instrumentation is provided by glibc itself.
|
||||
|
||||
This is a debug/development option and the default is to disable
|
||||
the instrumentation.
|
||||
@end table
|
||||
|
||||
To build the library and related programs, type @code{make}. This will
|
||||
|
||||
@@ -23,6 +23,8 @@ static const struct test_f_i_data isnan_test_data[] =
|
||||
TEST_f_b (isnan, 0, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, minus_zero, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, 10, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, 4294967297, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, -4294967297, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, min_subnorm_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, -min_subnorm_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
TEST_f_b (isnan, min_value, 0, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
FLOAT
|
||||
M_DECL_FUNC (__significand) (FLOAT x)
|
||||
{
|
||||
return M_SUF (__ieee754_scalb) (x,(FLOAT) - M_SUF (__ilogb) (x));
|
||||
int ex = - (unsigned int) M_SUF (__ilogb) (x);
|
||||
return M_SUF (__ieee754_scalb) (x,(FLOAT) ex);
|
||||
}
|
||||
|
||||
/* Don't provide _FloatN aliases for significand which was originally
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
|
||||
#include <support/support.h>
|
||||
|
||||
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
|
||||
#define assume_nonnull(x) assume ((x) != NULL)
|
||||
|
||||
/*
|
||||
The following define is necessary for glibc 2.0.6
|
||||
*/
|
||||
@@ -175,11 +178,17 @@ test_hosts (void)
|
||||
hptr1 = gethostbyname2 ("localhost", AF_INET);
|
||||
output_hostent ("gethostbyname2 (\"localhost\", AF_INET)", hptr1);
|
||||
|
||||
name = xmalloc (2);
|
||||
namelen += 2;
|
||||
|
||||
while (gethostname (name, namelen) < 0 && errno == ENAMETOOLONG)
|
||||
{
|
||||
namelen += 2; /* tiny increments to test a lot */
|
||||
name = xrealloc (name, namelen);
|
||||
}
|
||||
|
||||
assume_nonnull (name);
|
||||
|
||||
if (gethostname (name, namelen) == 0)
|
||||
{
|
||||
printf ("Hostname: %s\n", name);
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ static int
|
||||
do_test (void)
|
||||
{
|
||||
size_t i, j;
|
||||
for (i = 0; i < 100; ++i)
|
||||
for (i = 1; i < 100; ++i)
|
||||
{
|
||||
for (j = 0; j < 8192; ++j)
|
||||
{
|
||||
|
||||
+3
-2
@@ -1397,9 +1397,10 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
|
||||
if (s.length < need
|
||||
&& !scratch_buffer_set_array_size (&s, need, 1))
|
||||
goto memory_error;
|
||||
char *p = mempcpy (s.data, directory, dirlen);
|
||||
char *pdata = s.data;
|
||||
char *p = mempcpy (pdata, directory, dirlen);
|
||||
*p = '/';
|
||||
p += p[-1] != '/';
|
||||
p += pdata[p - pdata - 1] != '/';
|
||||
memcpy (p, d.name, namelen + 1);
|
||||
if (! is_dir (s.data, flags, pglob))
|
||||
continue;
|
||||
|
||||
+1
-10
@@ -801,7 +801,7 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
{
|
||||
if (EXT(statp).nssocks[ns] == -1) {
|
||||
struct sockaddr *nsap = __res_get_nsaddr (statp, ns);
|
||||
socklen_t slen;
|
||||
socklen_t slen = 0;
|
||||
|
||||
/* only try IPv6 if IPv6 NS and if not failed before */
|
||||
if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
|
||||
@@ -845,16 +845,7 @@ reopen (res_state statp, int *terrno, int ns)
|
||||
* error message is received. We can thus detect
|
||||
* the absence of a nameserver without timing out.
|
||||
*/
|
||||
/* With GCC 5.3 when compiling with -Os the compiler
|
||||
emits a warning that slen may be used uninitialized,
|
||||
but that is never true. Both slen and
|
||||
EXT(statp).nssocks[ns] are initialized together or
|
||||
the function return -1 before control flow reaches
|
||||
the call to connect with slen. */
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||||
if (__connect (EXT (statp).nssocks[ns], nsap, slen) < 0) {
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
__res_iclose(statp, false);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
|
||||
#include <support/next_to_fault.h>
|
||||
|
||||
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
|
||||
#define assume_nonnull(x) assume ((x) != NULL)
|
||||
|
||||
#define SPRINTF_BUFFER_SIZE 65536
|
||||
|
||||
static struct support_next_to_fault ntf;
|
||||
@@ -42,6 +45,7 @@ printf_under_test_fini (void)
|
||||
({ \
|
||||
__label__ out; \
|
||||
char *str = ntf.buffer; \
|
||||
assume_nonnull (str); \
|
||||
int result; \
|
||||
\
|
||||
result = sprintf (str, __VA_ARGS__); \
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
|
||||
#include <support/next_to_fault.h>
|
||||
|
||||
#define assume(R) ((R) ? (void) 0 : __builtin_unreachable ())
|
||||
#define assume_nonnull(x) assume ((x) != NULL)
|
||||
|
||||
#define SPRINTF_BUFFER_SIZE 65536
|
||||
|
||||
static struct support_next_to_fault ntf;
|
||||
@@ -43,6 +46,7 @@ static int
|
||||
printf_under_test (const char *restrict fmt, ...)
|
||||
{
|
||||
char *str = ntf.buffer;
|
||||
assume_nonnull (str);
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
|
||||
@@ -38,7 +38,8 @@ LABEL (form_integer):
|
||||
{
|
||||
long long int signed_number = process_arg_long_long_int ();
|
||||
is_negative = signed_number < 0;
|
||||
number.longlong = is_negative ? (- signed_number) : signed_number;
|
||||
number.longlong = is_negative ? (- (unsigned long long) signed_number)
|
||||
: signed_number;
|
||||
|
||||
goto LABEL (longlong_number);
|
||||
}
|
||||
@@ -55,7 +56,8 @@ LABEL (form_integer):
|
||||
signed_number = (short int) process_arg_unsigned_int ();
|
||||
|
||||
is_negative = signed_number < 0;
|
||||
number.word = is_negative ? (- signed_number) : signed_number;
|
||||
number.word = is_negative ? (- (unsigned long) signed_number)
|
||||
: signed_number;
|
||||
|
||||
goto LABEL (number);
|
||||
}
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ __erand48_r (unsigned short int xsubi[3], struct drand48_data *buffer,
|
||||
temp.ieee.negative = 0;
|
||||
temp.ieee.exponent = IEEE754_DOUBLE_BIAS;
|
||||
temp.ieee.mantissa0 = (xsubi[2] << 4) | (xsubi[1] >> 12);
|
||||
temp.ieee.mantissa1 = ((xsubi[1] & 0xfff) << 20) | (xsubi[0] << 4);
|
||||
temp.ieee.mantissa1 = (((uint32_t)xsubi[1] & 0xfff) << 20)
|
||||
| ((uint32_t)xsubi[0] << 4);
|
||||
|
||||
/* Please note the lower 4 bits of mantissa1 are always 0. */
|
||||
*result = temp.d - 1.0;
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ __jrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer,
|
||||
return -1;
|
||||
|
||||
/* Store the result. */
|
||||
*result = (int32_t) ((xsubi[2] << 16) | xsubi[1]);
|
||||
*result = (int32_t) (((uint32_t)xsubi[2] << 16) | (uint32_t)xsubi[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-7
@@ -44,13 +44,8 @@ __BEGIN_DECLS
|
||||
/* Use __pacify_uint16 (N) instead of (uint16_t) (N) when the cast is helpful
|
||||
only to pacify older GCC (e.g., GCC 10 -Wconversion) or non-GCC (e.g
|
||||
clang -Wimplicit-int-conversion). */
|
||||
#if __GNUC_PREREQ (11, 0)
|
||||
# define __pacify_uint8(n) (n)
|
||||
# define __pacify_uint16(n) (n)
|
||||
#else
|
||||
# define __pacify_uint8(n) ((uint8_t) (n))
|
||||
# define __pacify_uint16(n) ((uint16_t) (n))
|
||||
#endif
|
||||
#define __pacify_uint8(n) ((uint8_t) (n))
|
||||
#define __pacify_uint16(n) ((uint16_t) (n))
|
||||
|
||||
/* Count leading zeros. */
|
||||
extern unsigned int stdc_leading_zeros_uc (unsigned char __x)
|
||||
|
||||
+5
-2
@@ -150,9 +150,11 @@ extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative);
|
||||
#if BITS_PER_MP_LIMB == 32
|
||||
# define MAX_DIG_PER_LIMB 9
|
||||
# define MAX_FAC_PER_LIMB 1000000000UL
|
||||
# define SHIFT_CTE(N) N ## U
|
||||
#elif BITS_PER_MP_LIMB == 64
|
||||
# define MAX_DIG_PER_LIMB 19
|
||||
# define MAX_FAC_PER_LIMB 10000000000000000000ULL
|
||||
# define SHIFT_CTE(N) N ## UL
|
||||
#else
|
||||
# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for"
|
||||
#endif
|
||||
@@ -1572,12 +1574,13 @@ ____STRTOF_INTERNAL (const STRING_TYPE *nptr, STRING_TYPE **endptr, int group,
|
||||
{
|
||||
if (bits + BITS_PER_MP_LIMB <= MANT_DIG)
|
||||
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE,
|
||||
BITS_PER_MP_LIMB, 0);
|
||||
BITS_PER_MP_LIMB, SHIFT_CTE (0));
|
||||
else
|
||||
{
|
||||
used = MANT_DIG - bits;
|
||||
if (used > 0)
|
||||
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used, 0);
|
||||
__mpn_lshift_1 (retval, RETURN_LIMB_SIZE, used,
|
||||
SHIFT_CTE (0));
|
||||
}
|
||||
bits += BITS_PER_MP_LIMB;
|
||||
}
|
||||
|
||||
+19
-11
@@ -26,6 +26,24 @@
|
||||
|
||||
char putenv_val[100] = VAR "=some longer value";
|
||||
|
||||
static int
|
||||
__attribute_disable_ubsan__
|
||||
check_null_argument (void)
|
||||
{
|
||||
/* This deliberately tests supplying a null pointer to a function whose
|
||||
argument is marked __attribute__ ((nonnull)). */
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT(5, "-Wnonnull");
|
||||
errno = 0;
|
||||
if (unsetenv (NULL) >= 0 || errno != EINVAL)
|
||||
{
|
||||
puts ("unsetenv #1 failed");
|
||||
return 1;
|
||||
}
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
@@ -189,17 +207,7 @@ do_test (void)
|
||||
result = 1;
|
||||
}
|
||||
|
||||
/* This deliberately tests supplying a null pointer to a function whose
|
||||
argument is marked __attribute__ ((nonnull)). */
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT(5, "-Wnonnull");
|
||||
errno = 0;
|
||||
if (unsetenv (NULL) >= 0 || errno != EINVAL)
|
||||
{
|
||||
puts ("unsetenv #1 failed");
|
||||
result = 1;
|
||||
}
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
result = check_null_argument ();
|
||||
|
||||
errno = 0;
|
||||
if (unsetenv ("") >= 0 || errno != EINVAL)
|
||||
|
||||
+12
-4
@@ -15,6 +15,14 @@ bitval (int bits)
|
||||
return val;
|
||||
}
|
||||
|
||||
static unsigned long long int
|
||||
ubitval (int bits)
|
||||
{
|
||||
unsigned long long int val = 0;
|
||||
while (bits-- > 0)
|
||||
val |= 1ull << bits;
|
||||
return val;
|
||||
}
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
@@ -41,19 +49,19 @@ do_test (void)
|
||||
TEST (INT_MIN, "d", (int) -bitval (sizeof (int) * CHAR_BIT - 1) - 1);
|
||||
TEST (INT_MAX, "d", (int) bitval (sizeof (int) * CHAR_BIT - 1));
|
||||
TEST (UINT_MAX, "u",
|
||||
(unsigned int) bitval (sizeof (unsigned int) * CHAR_BIT));
|
||||
(unsigned int) ubitval (sizeof (unsigned int) * CHAR_BIT));
|
||||
|
||||
TEST (LONG_MIN, "ld",
|
||||
(long int) -bitval (sizeof (long int) * CHAR_BIT - 1) - 1);
|
||||
TEST (LONG_MAX, "ld", (long int) bitval (sizeof (long int) * CHAR_BIT - 1));
|
||||
TEST (ULONG_MAX, "lu",
|
||||
(unsigned long int) bitval (sizeof (unsigned long int) * CHAR_BIT));
|
||||
(unsigned long int) ubitval (sizeof (unsigned long int) * CHAR_BIT));
|
||||
|
||||
TEST (LLONG_MIN, "lld", -bitval (sizeof (long long int) * CHAR_BIT - 1) - 1);
|
||||
TEST (LLONG_MAX, "lld", bitval (sizeof (long long int) * CHAR_BIT - 1));
|
||||
TEST (ULLONG_MAX, "llu",
|
||||
(unsigned long long int) bitval (sizeof (unsigned long long int)
|
||||
* CHAR_BIT));
|
||||
(unsigned long long int) ubitval (sizeof (unsigned long long int)
|
||||
* CHAR_BIT));
|
||||
|
||||
/* Values from POSIX and Unix. */
|
||||
#ifdef PAGESIZE
|
||||
|
||||
+34
-34
@@ -53,23 +53,23 @@ f1 (int a00, int a01, int a02, int a03, int a04, int a05, int a06, int a07,
|
||||
a24, a25, a26, a27, a28, a29, a30, a31,
|
||||
a32, flag);
|
||||
|
||||
if (a00 != (0x00000001 << flag) || a01 != (0x00000004 << flag)
|
||||
|| a02 != (0x00000012 << flag) || a03 != (0x00000048 << flag)
|
||||
|| a04 != (0x00000123 << flag) || a05 != (0x0000048d << flag)
|
||||
|| a06 != (0x00001234 << flag) || a07 != (0x000048d1 << flag)
|
||||
|| a08 != (0x00012345 << flag) || a09 != (0x00048d15 << flag)
|
||||
|| a10 != (0x00123456 << flag) || a11 != (0x0048d159 << flag)
|
||||
|| a12 != (0x01234567 << flag) || a13 != (0x048d159e << flag)
|
||||
|| a14 != (0x12345678 << flag) || a15 != (0x48d159e2 << flag)
|
||||
|| a16 != (0x23456789 << flag) || a17 != (0x8d159e26 << flag)
|
||||
|| a18 != (0x3456789a << flag) || a19 != (0xd159e26a << flag)
|
||||
|| a20 != (0x456789ab << flag) || a21 != (0x159e26af << flag)
|
||||
|| a22 != (0x56789abc << flag) || a23 != (0x59e26af3 << flag)
|
||||
|| a24 != (0x6789abcd << flag) || a25 != (0x9e26af37 << flag)
|
||||
|| a26 != (0x789abcde << flag) || a27 != (0xe26af37b << flag)
|
||||
|| a28 != (0x89abcdef << flag) || a29 != (0x26af37bc << flag)
|
||||
|| a30 != (0x9abcdef0 << flag) || a31 != (0x6af37bc3 << flag)
|
||||
|| a32 != (0xabcdef0f << flag))
|
||||
if (a00 != (0x00000001u << flag) || a01 != (0x00000004u << flag)
|
||||
|| a02 != (0x00000012u << flag) || a03 != (0x00000048u << flag)
|
||||
|| a04 != (0x00000123u << flag) || a05 != (0x0000048du << flag)
|
||||
|| a06 != (0x00001234u << flag) || a07 != (0x000048d1u << flag)
|
||||
|| a08 != (0x00012345u << flag) || a09 != (0x00048d15u << flag)
|
||||
|| a10 != (0x00123456u << flag) || a11 != (0x0048d159u << flag)
|
||||
|| a12 != (0x01234567u << flag) || a13 != (0x048d159eu << flag)
|
||||
|| a14 != (0x12345678u << flag) || a15 != (0x48d159e2u << flag)
|
||||
|| a16 != (0x23456789u << flag) || a17 != (0x8d159e26u << flag)
|
||||
|| a18 != (0x3456789au << flag) || a19 != (0xd159e26au << flag)
|
||||
|| a20 != (0x456789abu << flag) || a21 != (0x159e26afu << flag)
|
||||
|| a22 != (0x56789abcu << flag) || a23 != (0x59e26af3u << flag)
|
||||
|| a24 != (0x6789abcdu << flag) || a25 != (0x9e26af37u << flag)
|
||||
|| a26 != (0x789abcdeu << flag) || a27 != (0xe26af37bu << flag)
|
||||
|| a28 != (0x89abcdefu << flag) || a29 != (0x26af37bcu << flag)
|
||||
|| a30 != (0x9abcdef0u << flag) || a31 != (0x6af37bc3u << flag)
|
||||
|| a32 != (0xabcdef0fu << flag))
|
||||
{
|
||||
puts ("arg mismatch");
|
||||
exit (-1);
|
||||
@@ -146,23 +146,23 @@ main (void)
|
||||
ctx[1].uc_link = &ctx[0];
|
||||
errno = 0;
|
||||
makecontext (&ctx[1], (void (*) (void)) f1, 33,
|
||||
0x00000001 << flag, 0x00000004 << flag,
|
||||
0x00000012 << flag, 0x00000048 << flag,
|
||||
0x00000123 << flag, 0x0000048d << flag,
|
||||
0x00001234 << flag, 0x000048d1 << flag,
|
||||
0x00012345 << flag, 0x00048d15 << flag,
|
||||
0x00123456 << flag, 0x0048d159 << flag,
|
||||
0x01234567 << flag, 0x048d159e << flag,
|
||||
0x12345678 << flag, 0x48d159e2 << flag,
|
||||
0x23456789 << flag, 0x8d159e26 << flag,
|
||||
0x3456789a << flag, 0xd159e26a << flag,
|
||||
0x456789ab << flag, 0x159e26af << flag,
|
||||
0x56789abc << flag, 0x59e26af3 << flag,
|
||||
0x6789abcd << flag, 0x9e26af37 << flag,
|
||||
0x789abcde << flag, 0xe26af37b << flag,
|
||||
0x89abcdef << flag, 0x26af37bc << flag,
|
||||
0x9abcdef0 << flag, 0x6af37bc3 << flag,
|
||||
0xabcdef0f << flag);
|
||||
0x00000001u << flag, 0x00000004u << flag,
|
||||
0x00000012u << flag, 0x00000048u << flag,
|
||||
0x00000123u << flag, 0x0000048du << flag,
|
||||
0x00001234u << flag, 0x000048d1u << flag,
|
||||
0x00012345u << flag, 0x00048d15u << flag,
|
||||
0x00123456u << flag, 0x0048d159u << flag,
|
||||
0x01234567u << flag, 0x048d159eu << flag,
|
||||
0x12345678u << flag, 0x48d159e2u << flag,
|
||||
0x23456789u << flag, 0x8d159e26u << flag,
|
||||
0x3456789au << flag, 0xd159e26au << flag,
|
||||
0x456789abu << flag, 0x159e26afu << flag,
|
||||
0x56789abcu << flag, 0x59e26af3u << flag,
|
||||
0x6789abcdu << flag, 0x9e26af37u << flag,
|
||||
0x789abcdeu << flag, 0xe26af37bu << flag,
|
||||
0x89abcdefu << flag, 0x26af37bcu << flag,
|
||||
0x9abcdef0u << flag, 0x6af37bc3u << flag,
|
||||
0xabcdef0fu << flag);
|
||||
|
||||
/* Without this check, a stub makecontext can make us spin forever. */
|
||||
if (errno == ENOSYS)
|
||||
|
||||
+3
-1
@@ -40,7 +40,9 @@ __ffs (int i)
|
||||
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
||||
};
|
||||
unsigned int a;
|
||||
unsigned int x = i & -i;
|
||||
/* Isolate the least significant one. */
|
||||
unsigned int u_i = i;
|
||||
unsigned int x = u_i & -u_i;
|
||||
|
||||
a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
|
||||
|
||||
|
||||
+3
-1
@@ -29,7 +29,9 @@ __ffsll (long long int i)
|
||||
#if USE_FFSLL_BUILTIN
|
||||
return __builtin_ffsll (i);
|
||||
#else
|
||||
unsigned long long int x = i & -i;
|
||||
/* Isolate the least significant one. */
|
||||
unsigned long long int i_u = i;
|
||||
unsigned long long int x = i_u & -i_u;
|
||||
|
||||
if (x <= 0xffffffff)
|
||||
return ffs (i);
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ stpcpy_unaligned_loop (op_t *restrict dst, const op_t *restrict src,
|
||||
}
|
||||
|
||||
/* Align the final partial of P2. */
|
||||
w2 = MERGE (w2b, sh_1, 0, sh_2);
|
||||
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ strcmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs)
|
||||
|
||||
/* Load the final word of P1 and align the final partial of P2. */
|
||||
w1 = *x1++;
|
||||
w2 = MERGE (w2b, sh_1, 0, sh_2);
|
||||
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
|
||||
}
|
||||
|
||||
return final_cmp (w1, w2);
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ strncmp_unaligned_loop (const op_t *x1, const op_t *x2, op_t w1, uintptr_t ofs,
|
||||
|
||||
/* Load the final word of P1 and align the final partial of P2. */
|
||||
w1 = *x1++;
|
||||
w2 = MERGE (w2b, sh_1, 0, sh_2);
|
||||
w2 = MERGE (w2b, sh_1, 0UL, sh_2);
|
||||
}
|
||||
|
||||
return final_cmp (w1, w2, n);
|
||||
|
||||
+3
-2
@@ -40,9 +40,10 @@ do_test (void)
|
||||
#define TEST(fct, type) \
|
||||
try (#fct, 0, fct ((type) 0), 0); \
|
||||
for (i=0 ; i < 8 * sizeof (type); i++) \
|
||||
try (#fct, 1ll << i, fct (((type) 1) << i), i + 1); \
|
||||
try (#fct, 1ull << i, fct (((unsigned type) 1) << i), i + 1); \
|
||||
for (i=0 ; i < 8 * sizeof (type) ; i++) \
|
||||
try (#fct, (~((type) 0) >> i) << i, fct ((~((type) 0) >> i) << i), i + 1);\
|
||||
try (#fct, (~((unsigned type) 0) >> i) << i, \
|
||||
fct ((~((unsigned type) 0) >> i) << i), i + 1);\
|
||||
try (#fct, 0x80008000, fct ((type) 0x80008000), 16)
|
||||
|
||||
TEST (ffs, int);
|
||||
|
||||
@@ -97,9 +97,9 @@ do_test (size_t align, size_t pos, size_t len, int seek_char, int max_char)
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
{
|
||||
buf[align + i] = (random () * random ()) & max_char;
|
||||
buf[align + i] = ((int64_t)random () * random ()) & max_char;
|
||||
if (!buf[align + i])
|
||||
buf[align + i] = (random () * random ()) & max_char;
|
||||
buf[align + i] = ((int64_t)random () * random ()) & max_char;
|
||||
if (!buf[align + i])
|
||||
buf[align + i] = 1;
|
||||
if ((i > pos || pos >= len) && buf[align + i] == seek_char)
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ xdr_hyper (XDR *xdrs, quad_t *llp)
|
||||
{
|
||||
if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2))
|
||||
return FALSE;
|
||||
*llp = ((quad_t) t1) << 32;
|
||||
*llp = ((u_quad_t) t1) << 32;
|
||||
*llp |= (uint32_t) t2;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -24,19 +24,19 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MIDR_PARTNUM_SHIFT 4
|
||||
#define MIDR_PARTNUM_MASK (0xfff << MIDR_PARTNUM_SHIFT)
|
||||
#define MIDR_PARTNUM_MASK (UINT64_C(0xfff) << MIDR_PARTNUM_SHIFT)
|
||||
#define MIDR_PARTNUM(midr) \
|
||||
(((midr) & MIDR_PARTNUM_MASK) >> MIDR_PARTNUM_SHIFT)
|
||||
#define MIDR_ARCHITECTURE_SHIFT 16
|
||||
#define MIDR_ARCHITECTURE_MASK (0xf << MIDR_ARCHITECTURE_SHIFT)
|
||||
#define MIDR_ARCHITECTURE_MASK (UINT64_C(0xf) << MIDR_ARCHITECTURE_SHIFT)
|
||||
#define MIDR_ARCHITECTURE(midr) \
|
||||
(((midr) & MIDR_ARCHITECTURE_MASK) >> MIDR_ARCHITECTURE_SHIFT)
|
||||
#define MIDR_VARIANT_SHIFT 20
|
||||
#define MIDR_VARIANT_MASK (0xf << MIDR_VARIANT_SHIFT)
|
||||
#define MIDR_VARIANT_MASK (UINT64_C(0xf) << MIDR_VARIANT_SHIFT)
|
||||
#define MIDR_VARIANT(midr) \
|
||||
(((midr) & MIDR_VARIANT_MASK) >> MIDR_VARIANT_SHIFT)
|
||||
#define MIDR_IMPLEMENTOR_SHIFT 24
|
||||
#define MIDR_IMPLEMENTOR_MASK (0xff << MIDR_IMPLEMENTOR_SHIFT)
|
||||
#define MIDR_IMPLEMENTOR_MASK (UINT64_C(0xff) << MIDR_IMPLEMENTOR_SHIFT)
|
||||
#define MIDR_IMPLEMENTOR(midr) \
|
||||
(((midr) & MIDR_IMPLEMENTOR_MASK) >> MIDR_IMPLEMENTOR_SHIFT)
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ $(objpfx)tst-armtlsdescextnow: $(objpfx)tst-armtlsdescextnowmod.so
|
||||
$(objpfx)tst-armtlsdescextlazy: $(objpfx)tst-armtlsdescextlazymod.so
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(enable-ubsan),yes)
|
||||
# aeabi_unwind_cpp_pr1 is built as rtld module
|
||||
CFLAGS-aeabi_unwind_cpp_pr1.c += -DDISABLE_USAN_INTERNAL_REDIR
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),csu)
|
||||
|
||||
@@ -84,7 +84,8 @@ extern int search_aux_cache (struct stat *stat_buf, int *flags,
|
||||
extern void add_to_aux_cache (struct stat *stat_buf, int flags,
|
||||
unsigned int isa_level, const char *soname);
|
||||
|
||||
extern void save_aux_cache (const char *aux_cache_name);
|
||||
extern void save_aux_cache (const char *aux_cache_name)
|
||||
__attribute__((nonnull (1)));
|
||||
|
||||
/* Declared in readlib.c. */
|
||||
extern int process_file (const char *real_file_name, const char *file_name,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <elf.h>
|
||||
#include <dlfcn.h>
|
||||
@@ -773,6 +774,8 @@ extern void _dl_debug_printf (const char *fmt, ...)
|
||||
extern void _dl_debug_printf_c (const char *fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2))) attribute_hidden;
|
||||
|
||||
extern void _dl_debug_vprintf_c (const char *fmt, va_list ap)
|
||||
__attribute__ ((__format__ (__printf__, 1, 0))) attribute_hidden;
|
||||
|
||||
/* Write a message on the specified descriptor FD. The parameters are
|
||||
interpreted as for a `printf' call. */
|
||||
|
||||
@@ -19,28 +19,11 @@
|
||||
#ifndef _STRING_FZI_H
|
||||
#define _STRING_FZI_H 1
|
||||
|
||||
#include <stdbit.h>
|
||||
#include <limits.h>
|
||||
#include <endian.h>
|
||||
#include <string-fza.h>
|
||||
|
||||
static __always_inline int
|
||||
clz (find_t c)
|
||||
{
|
||||
if (sizeof (find_t) == sizeof (unsigned long))
|
||||
return __builtin_clzl (c);
|
||||
else
|
||||
return __builtin_clzll (c);
|
||||
}
|
||||
|
||||
static __always_inline int
|
||||
ctz (find_t c)
|
||||
{
|
||||
if (sizeof (find_t) == sizeof (unsigned long))
|
||||
return __builtin_ctzl (c);
|
||||
else
|
||||
return __builtin_ctzll (c);
|
||||
}
|
||||
|
||||
/* A subroutine for the index_zero functions. Given a test word C, return
|
||||
the (memory order) index of the first byte (in memory order) that is
|
||||
non-zero. */
|
||||
@@ -49,9 +32,9 @@ index_first (find_t c)
|
||||
{
|
||||
int r;
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
r = ctz (c);
|
||||
r = stdc_trailing_zeros (c);
|
||||
else
|
||||
r = clz (c);
|
||||
r = stdc_leading_zeros (c);
|
||||
return r / CHAR_BIT;
|
||||
}
|
||||
|
||||
@@ -62,9 +45,9 @@ index_last (find_t c)
|
||||
{
|
||||
int r;
|
||||
if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
r = clz (c);
|
||||
r = stdc_leading_zeros (c);
|
||||
else
|
||||
r = ctz (c);
|
||||
r = stdc_trailing_zeros (c);
|
||||
return sizeof (find_t) - 1 - (r / CHAR_BIT);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,3 +18,39 @@ asm (".hidden __stack_chk_fail_local\n"
|
||||
"__stack_chk_fail = __stack_chk_fail_local");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined __ASSEMBLER__ && IS_IN(rtld) && defined ENABLE_UBSAN \
|
||||
&& !defined DISABLE_USAN_INTERNAL_REDIR
|
||||
/* These are autogenerated by the compiler, so no subject to either
|
||||
hidden_attribute or hidden_proto alias definition. */
|
||||
asm ("__ubsan_handle_negate_overflow = "
|
||||
"__GI___ubsan_handle_negate_overflow");
|
||||
asm ("__ubsan_handle_shift_out_of_bounds = "
|
||||
"__GI___ubsan_handle_shift_out_of_bounds");
|
||||
asm ("__ubsan_handle_divrem_overflow = "
|
||||
"__GI___ubsan_handle_divrem_overflow");
|
||||
asm ("__ubsan_handle_vla_bound_not_positive = "
|
||||
"__GI___ubsan_handle_vla_bound_not_positive");
|
||||
asm ("__ubsan_handle_pointer_overflow = "
|
||||
"__GI___ubsan_handle_pointer_overflow");
|
||||
asm ("__ubsan_handle_load_invalid_value ="
|
||||
"__GI___ubsan_handle_load_invalid_value");
|
||||
asm ("__ubsan_handle_out_of_bounds = "
|
||||
"__GI___ubsan_handle_out_of_bounds");
|
||||
asm ("__ubsan_handle_sub_overflow = "
|
||||
"__GI___ubsan_handle_sub_overflow");
|
||||
asm ("__ubsan_handle_add_overflow = "
|
||||
"__GI___ubsan_handle_add_overflow");
|
||||
asm ("__ubsan_handle_mul_overflow = "
|
||||
"__GI___ubsan_handle_mul_overflow");
|
||||
asm ("__ubsan_handle_type_mismatch_v1 = "
|
||||
"__GI___ubsan_handle_type_mismatch_v1");
|
||||
asm ("__ubsan_handle_nonnull_return_v1 = "
|
||||
"__GI___ubsan_handle_nonnull_return_v1");
|
||||
asm ("__ubsan_handle_nonnull_arg = "
|
||||
"__GI___ubsan_handle_nonnull_arg");
|
||||
asm ("__ubsan_handle_invalid_builtin = "
|
||||
"__GI___ubsan_handle_invalid_builtin");
|
||||
asm ("__ubsan_handle_builtin_unreachable = "
|
||||
"__GI___ubsan_handle_builtin_unreachable");
|
||||
#endif
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
RCSID("$NetBSD: s_ilogb.S,v 1.5 1995/10/12 15:53:09 jtc Exp $")
|
||||
|
||||
ENTRY(__ieee754_ilogb)
|
||||
fldl 4(%esp)
|
||||
/* I added the following ugly construct because ilogb(+-Inf) is
|
||||
required to return INT_MAX in ISO C99.
|
||||
-- jakub@redhat.com. */
|
||||
fxam /* Is NaN or +-Inf? */
|
||||
fstsw %ax
|
||||
movb $0x45, %dh
|
||||
andb %ah, %dh
|
||||
cmpb $0x05, %dh
|
||||
je 1f /* Is +-Inf, jump. */
|
||||
cmpb $0x40, %dh
|
||||
je 2f /* Is +-0, jump. */
|
||||
|
||||
fxtract
|
||||
pushl %eax
|
||||
cfi_adjust_cfa_offset (4)
|
||||
fstp %st
|
||||
|
||||
fistpl (%esp)
|
||||
fwait
|
||||
popl %eax
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
|
||||
ret
|
||||
|
||||
1: fstp %st
|
||||
movl $0x7fffffff, %eax
|
||||
ret
|
||||
2: fstp %st
|
||||
movl $0x80000000, %eax /* FP_ILOGB0 */
|
||||
ret
|
||||
END (__ieee754_ilogb)
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Public domain.
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
|
||||
RCSID("$NetBSD: s_ilogbf.S,v 1.4 1995/10/22 20:32:43 pk Exp $")
|
||||
|
||||
ENTRY(__ieee754_ilogbf)
|
||||
flds 4(%esp)
|
||||
/* I added the following ugly construct because ilogb(+-Inf) is
|
||||
required to return INT_MAX in ISO C99.
|
||||
-- jakub@redhat.com. */
|
||||
fxam /* Is NaN or +-Inf? */
|
||||
fstsw %ax
|
||||
movb $0x45, %dh
|
||||
andb %ah, %dh
|
||||
cmpb $0x05, %dh
|
||||
je 1f /* Is +-Inf, jump. */
|
||||
cmpb $0x40, %dh
|
||||
je 2f /* Is +-0, jump. */
|
||||
|
||||
fxtract
|
||||
pushl %eax
|
||||
cfi_adjust_cfa_offset (4)
|
||||
fstp %st
|
||||
|
||||
fistpl (%esp)
|
||||
fwait
|
||||
popl %eax
|
||||
cfi_adjust_cfa_offset (-4)
|
||||
|
||||
ret
|
||||
|
||||
1: fstp %st
|
||||
movl $0x7fffffff, %eax
|
||||
ret
|
||||
2: fstp %st
|
||||
movl $0x80000000, %eax /* FP_ILOGB0 */
|
||||
ret
|
||||
END (__ieee754_ilogbf)
|
||||
@@ -1 +0,0 @@
|
||||
/* Not needed. */
|
||||
@@ -1,63 +1 @@
|
||||
/* @(#)s_ilogb.c 5.1 93/09/24 */
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#if defined(LIBM_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$NetBSD: s_ilogb.c,v 1.9 1995/05/10 20:47:28 jtc Exp $";
|
||||
#endif
|
||||
|
||||
/* ilogb(double x)
|
||||
* return the binary exponent of non-zero x
|
||||
* ilogb(0) = FP_ILOGB0
|
||||
* ilogb(NaN) = FP_ILOGBNAN (no signal is raised)
|
||||
* ilogb(+-Inf) = INT_MAX (no signal is raised)
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <math_private.h>
|
||||
|
||||
int
|
||||
__ieee754_ilogb (double x)
|
||||
{
|
||||
int32_t hx, lx, ix;
|
||||
|
||||
GET_HIGH_WORD (hx, x);
|
||||
hx &= 0x7fffffff;
|
||||
if (hx < 0x00100000)
|
||||
{
|
||||
GET_LOW_WORD (lx, x);
|
||||
if ((hx | lx) == 0)
|
||||
return FP_ILOGB0; /* ilogb(0) = FP_ILOGB0 */
|
||||
else /* subnormal x */
|
||||
if (hx == 0)
|
||||
{
|
||||
for (ix = -1043; lx > 0; lx <<= 1)
|
||||
ix -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ix = -1022, hx <<= 11; hx > 0; hx <<= 1)
|
||||
ix -= 1;
|
||||
}
|
||||
return ix;
|
||||
}
|
||||
else if (hx < 0x7ff00000)
|
||||
return (hx >> 20) - 1023;
|
||||
else if (FP_ILOGBNAN != INT_MAX)
|
||||
{
|
||||
/* ISO C99 requires ilogb(+-Inf) == INT_MAX. */
|
||||
GET_LOW_WORD (lx, x);
|
||||
if (((hx ^ 0x7ff00000) | lx) == 0)
|
||||
return INT_MAX;
|
||||
}
|
||||
return FP_ILOGBNAN;
|
||||
}
|
||||
/* ilogb is implemented at w_ilogb.c */
|
||||
|
||||
@@ -164,6 +164,8 @@ attribute_hidden double __math_divzero (uint32_t);
|
||||
|
||||
/* Invalid input unless it is a quiet NaN. */
|
||||
attribute_hidden double __math_invalid (double);
|
||||
attribute_hidden int __math_invalid_i (int);
|
||||
attribute_hidden long int __math_invalid_li (long int);
|
||||
|
||||
/* Error handling using output checking, only for errno setting. */
|
||||
|
||||
|
||||
@@ -29,8 +29,24 @@ with_errno (double y, int e)
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
|
||||
NOINLINE static int
|
||||
with_errno_i (int y, int e)
|
||||
{
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
|
||||
NOINLINE static long int
|
||||
with_errno_li (long int y, int e)
|
||||
{
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
#else
|
||||
#define with_errno(x, e) (x)
|
||||
#define with_errno_i(x, e) (x)
|
||||
#define with_errno_li(x, e) (x)
|
||||
#endif
|
||||
|
||||
attribute_hidden double
|
||||
@@ -83,6 +99,22 @@ __math_invalid (double x)
|
||||
return isnan (x) ? y : with_errno (y, EDOM);
|
||||
}
|
||||
|
||||
attribute_hidden int
|
||||
__math_invalid_i (int r)
|
||||
{
|
||||
double y = 0.0 / 0.0;
|
||||
math_force_eval (y);
|
||||
return with_errno_i (r, EDOM);
|
||||
}
|
||||
|
||||
attribute_hidden long int
|
||||
__math_invalid_li (long int r)
|
||||
{
|
||||
double y = 0.0 / 0.0;
|
||||
math_force_eval (y);
|
||||
return with_errno_li (r, EDOM);
|
||||
}
|
||||
|
||||
/* Check result and set errno if necessary. */
|
||||
|
||||
attribute_hidden double
|
||||
|
||||
@@ -239,7 +239,7 @@ __expm1 (double x)
|
||||
uint32_t high;
|
||||
y = one - (e - x);
|
||||
GET_HIGH_WORD (high, y);
|
||||
SET_HIGH_WORD (y, high + (k << 20)); /* add k to y's exponent */
|
||||
SET_HIGH_WORD (y, high + ((uint32_t)k << 20)); /* add k to y's exponent */
|
||||
return y - one;
|
||||
}
|
||||
t = one;
|
||||
|
||||
@@ -95,7 +95,7 @@ __lrint (double x)
|
||||
if (j0 == 20)
|
||||
result = (long int) i0;
|
||||
else
|
||||
result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0));
|
||||
result = (i0 << (j0 - 20)) | (i1 >> (52 - j0));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -37,7 +37,8 @@ __rint (double x)
|
||||
4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
|
||||
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
|
||||
};
|
||||
int64_t i0, sx;
|
||||
int64_t i0;
|
||||
uint64_t sx;
|
||||
int32_t j0;
|
||||
EXTRACT_WORDS64 (i0, x);
|
||||
sx = (i0 >> 63) & 1;
|
||||
|
||||
@@ -37,7 +37,9 @@ FUNC (double *x, double payload)
|
||||
except for 0 when allowed; (c) not an integer. */
|
||||
if (exponent >= BIAS + PAYLOAD_DIG
|
||||
|| (exponent < BIAS && !(SET_HIGH_BIT && ix == 0))
|
||||
|| (ix & ((1ULL << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0)
|
||||
|| ((BIAS + EXPLICIT_MANT_DIG - exponent) < 64
|
||||
&& (ix & ((1ULL << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1))
|
||||
!= 0))
|
||||
{
|
||||
INSERT_WORDS64 (*x, 0);
|
||||
return 1;
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Get integer exponent of a floating-point value.
|
||||
Copyright (C) 1999-2025 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/>. */
|
||||
|
||||
static inline RET_TYPE
|
||||
IMPL_NAME (double x)
|
||||
{
|
||||
uint64_t ux = asuint64 (x);
|
||||
int ex = (ux & ~SIGN_MASK) >> MANTISSA_WIDTH;
|
||||
if (__glibc_unlikely (ex == 0)) /* zero or subnormal */
|
||||
{
|
||||
/* Clear sign and exponent */
|
||||
ux <<= 12;
|
||||
if (ux == 0)
|
||||
return RET_INVALID (RET_LOGB0);
|
||||
/* subnormal */
|
||||
return (RET_TYPE)-1023 - stdc_leading_zeros (ux);
|
||||
}
|
||||
if (__glibc_unlikely (ex == EXPONENT_MASK >> MANTISSA_WIDTH))
|
||||
/* NaN or Inf */
|
||||
return RET_INVALID (ux << 12 ? RET_LOGBNAN : RET_LOGMAX);
|
||||
return ex - 1023;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Get integer exponent of a floating-point value.
|
||||
Copyright (C) 1999-2025 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 <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdbit.h>
|
||||
#include <libm-alias-double.h>
|
||||
#include "math_config.h"
|
||||
|
||||
#ifdef DEF_AS_LLOGB
|
||||
# define DECL_NAME __llogb
|
||||
# define FUNC_NAME llogb
|
||||
# define RET_TYPE long int
|
||||
# define RET_LOGB0 FP_LLOGB0
|
||||
# define RET_LOGBNAN FP_LLOGBNAN
|
||||
# define RET_LOGMAX LONG_MAX
|
||||
# define RET_INVALID __math_invalid_li
|
||||
#else
|
||||
# define DECL_NAME __ilogb
|
||||
# define FUNC_NAME ilogb
|
||||
# define RET_TYPE int
|
||||
# define RET_LOGB0 FP_ILOGB0
|
||||
# define RET_LOGBNAN FP_ILOGBNAN
|
||||
# define RET_LOGMAX INT_MAX
|
||||
# define RET_INVALID __math_invalid_i
|
||||
#endif
|
||||
#define __IMPL_NAME(x,y) x ## _ ## y
|
||||
#define _IMPL_NAME(x,y) __IMPL_NAME(x,y)
|
||||
#define IMPL_NAME _IMPL_NAME(FUNC_NAME, impl)
|
||||
#include <w_ilogb-impl.h>
|
||||
|
||||
RET_TYPE
|
||||
DECL_NAME (double x)
|
||||
{
|
||||
return IMPL_NAME (x);
|
||||
}
|
||||
libm_alias_double (DECL_NAME, FUNC_NAME)
|
||||
@@ -0,0 +1,2 @@
|
||||
#define DEF_AS_LLOGB
|
||||
#include "w_ilogb.c"
|
||||
@@ -1,43 +1 @@
|
||||
/* s_ilogbf.c -- float version of s_ilogb.c.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ====================================================
|
||||
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
*
|
||||
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||
* Permission to use, copy, modify, and distribute this
|
||||
* software is freely granted, provided that this notice
|
||||
* is preserved.
|
||||
* ====================================================
|
||||
*/
|
||||
|
||||
#if defined(LIBM_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$NetBSD: s_ilogbf.c,v 1.4 1995/05/10 20:47:31 jtc Exp $";
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <math_private.h>
|
||||
|
||||
int __ieee754_ilogbf(float x)
|
||||
{
|
||||
int32_t hx,ix;
|
||||
|
||||
GET_FLOAT_WORD(hx,x);
|
||||
hx &= 0x7fffffff;
|
||||
if(hx<0x00800000) {
|
||||
if(hx==0)
|
||||
return FP_ILOGB0; /* ilogb(0) = FP_ILOGB0 */
|
||||
else /* subnormal x */
|
||||
for (ix = -126,hx<<=8; hx>0; hx<<=1) ix -=1;
|
||||
return ix;
|
||||
}
|
||||
else if (hx<0x7f800000) return (hx>>23)-127;
|
||||
else if (FP_ILOGBNAN != INT_MAX) {
|
||||
/* ISO C99 requires ilogbf(+-Inf) == INT_MAX. */
|
||||
if (hx==0x7f800000)
|
||||
return INT_MAX;
|
||||
}
|
||||
return FP_ILOGBNAN;
|
||||
}
|
||||
/* ilogbf is implemented at w_ilogbf.c */
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <math_private.h>
|
||||
#include <nan-high-order-bit.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbit.h>
|
||||
|
||||
#ifndef WANT_ROUNDING
|
||||
/* Correct special case results in non-nearest rounding modes. */
|
||||
@@ -102,7 +103,7 @@ roundevenf_finite (float x)
|
||||
{
|
||||
union { float f; uint32_t i; } u = {y};
|
||||
union { float f; uint32_t i; } v = {y - copysignf (1.0, x)};
|
||||
if (__builtin_ctzl (v.i) > __builtin_ctzl (u.i))
|
||||
if (stdc_leading_zeros (v.i) > stdc_leading_zeros (u.i))
|
||||
y = v.f;
|
||||
}
|
||||
return y;
|
||||
@@ -208,6 +209,8 @@ attribute_hidden float __math_uflowf (uint32_t);
|
||||
attribute_hidden float __math_may_uflowf (uint32_t);
|
||||
attribute_hidden float __math_divzerof (uint32_t);
|
||||
attribute_hidden float __math_invalidf (float);
|
||||
attribute_hidden int __math_invalidf_i (int);
|
||||
attribute_hidden long int __math_invalidf_li (long int);
|
||||
attribute_hidden float __math_edomf (float x);
|
||||
|
||||
/* Shared between expf, exp2f, exp10f, and powf. */
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <math-barriers.h>
|
||||
#include "math_config.h"
|
||||
|
||||
#if WANT_ERRNO
|
||||
@@ -27,8 +28,24 @@ with_errnof (float y, int e)
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
|
||||
NOINLINE static int
|
||||
with_errnof_i (int y, int e)
|
||||
{
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
|
||||
NOINLINE static long int
|
||||
with_errnof_li (long int y, int e)
|
||||
{
|
||||
errno = e;
|
||||
return y;
|
||||
}
|
||||
#else
|
||||
# define with_errnof(x, e) (x)
|
||||
# define with_errnof_i(x, x) (x)
|
||||
# define with_errnof_li(x, x) (x)
|
||||
#endif
|
||||
|
||||
attribute_hidden float
|
||||
@@ -80,3 +97,19 @@ __math_invalidf (float x)
|
||||
float y = (x - x) / (x - x);
|
||||
return isnan (x) ? y : with_errnof (y, EDOM);
|
||||
}
|
||||
|
||||
attribute_hidden int
|
||||
__math_invalidf_i (int x)
|
||||
{
|
||||
float y = 0.0f / 0.0f;
|
||||
math_force_eval (y);
|
||||
return with_errnof_i (x, EDOM);
|
||||
}
|
||||
|
||||
attribute_hidden long int
|
||||
__math_invalidf_li (long int x)
|
||||
{
|
||||
float y = 0.0f / 0.0f;
|
||||
math_force_eval (y);
|
||||
return with_errnof_li (x, EDOM);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ __nearbyintf (float x)
|
||||
-8.3886080000e+06, /* 0xcb000000 */
|
||||
};
|
||||
fenv_t env;
|
||||
int32_t i0, j0, sx;
|
||||
int32_t i0, j0;
|
||||
uint32_t sx;
|
||||
float w, t;
|
||||
GET_FLOAT_WORD (i0, x);
|
||||
sx = (i0 >> 31) & 1;
|
||||
|
||||
@@ -30,7 +30,8 @@ __rintf (float x)
|
||||
8.3886080000e+06, /* 0x4b000000 */
|
||||
-8.3886080000e+06, /* 0xcb000000 */
|
||||
};
|
||||
int32_t i0, j0, sx;
|
||||
int32_t i0, j0;
|
||||
uint32_t sx;
|
||||
float w, t;
|
||||
GET_FLOAT_WORD (i0, x);
|
||||
sx = (i0 >> 31) & 1;
|
||||
|
||||
@@ -37,7 +37,8 @@ FUNC (float *x, float payload)
|
||||
except for 0 when allowed; (c) not an integer. */
|
||||
if (exponent >= BIAS + PAYLOAD_DIG
|
||||
|| (exponent < BIAS && !(SET_HIGH_BIT && ix == 0))
|
||||
|| (ix & ((1U << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0)
|
||||
|| ((BIAS + EXPLICIT_MANT_DIG - exponent) < 32
|
||||
&& (ix & ((1U << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0))
|
||||
{
|
||||
SET_FLOAT_WORD (*x, 0);
|
||||
return 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user