| Age | Commit message (Collapse) | Author | Lines |
|
the new condition also allows forward progress into ordinary matching
if the pattern begins with a backslash. this is fine independent of
FNM_NOESCAPE and independent of what follows the backslash; if
FNM_NOESCAPE is active, the backslash is literal and will not match.
if FNM_NOESCAPE is not active, the pattern beginning with a backslash
ensures that the first character is literal.
|
|
previously, the malloc-failure error path cleared it, but other
failures from vsnprintf such as EILSEQ or EOVERFLOW left the original
contents of the result object in place.
leaving any old value in place is allowed, and would be required if
the specification did not explicitly permit clobbering it on failure,
but it does.
by overwriting any old value there with a null pointer, we harden
callers that might have failed to check the return value for errors
against accessing and possibly exposing unrelated data; instead they
will fault on dereference.
|
|
in this case, negation produces integer overflow. since a field width
of the faithfully negated value would necessarily overflow INT_MAX,
just detect this case and immediately treat it as an output overflow
error.
|
|
this magic number 4 is what ensures the next wctomb won't overflow the
allocated buffer, but its purpose wasn't clear.
|
|
Allocated narrow %c conversions initially reserve only width+1 bytes.
For the default width this is two bytes, but in a UTF-8 locale wctomb
can write up to MB_LEN_MAX bytes into the buffer before the
post-conversion growth check, overflowing the two-byte allocation for
a three- or four-byte input character.
Ensure every allocated narrow buffer starts at no less than
MB_LEN_MAX bytes. The existing geometric growth then keeps at least
MB_LEN_MAX spare bytes available after each conversion.
|
|
on archs with 32-bit size_t, multiplying the caller-provided signed
int field width by sizeof(wchar_t) can overflow.
we could explicitly error out, but just replacing the requested size
to let malloc fail avoids the need to poke at errno, and the rest of
the function here is already using guaranteed-fail in the geometric
buffer growth path to avoid explicit size checks.
|
|
added 'set --' so $@, $*, $#, $1, $2 are cleared
(does not seem to be in the spec, but cleaner)
wordexp("$*", p, 0)
was "$*","2>/dev/stderr", now empty list.
|
|
stderr redirection to /dev/null didn't work, can be done in the
command, but would not redirect errors printed during sh startup.
wordexp(")", p, 0)
clobbered stderr, now silent.
|
|
On an unsuccessful search, the backwards loop decrements the pointer
past the beginning of the string and then compares that invalid pointer
with the string pointer.
Check for the beginning of the string before decrementing instead. This
preserves the existing results without forming a pointer outside the
array.
|
|
The continue for lines longer than INT_MAX reaches the do-while
condition without initializing n. On the first such line, the condition
reads indeterminate values. After an earlier line, it reuses stale
offsets from that line.
Jump directly to the start of the loop instead. This is the minimal form
requested in the previous review and preserves the intended behavior of
skipping an overlong line.
|
|
the new code uses that for all real |x| in [0x1p-999,0x1p999]
y = (float)x
is the same as
r = (double)x
t = x - r
if (t!=0 && r.bits%2==0)
r.bits += (r<0)==(t<0) ? 1 : -1
y = (float)r
in all rounding modes, with the same fenv effects.
this can be interpreted as a round to odd adjustment[1].
in fmaf t is computed with a fast2sum variant.
- optimized common case.
- implicit uflow handling instead of fenv calls.
- no fegetround check.
- no api calls on hf targets.
- fixed missed uflow on targets that signal it before rounding:
fmaf(-0x1p-100f, 0x1p-100f, 0x1p-126f)
- removed freebsd code references and comments.
- fmaf.o code size vs before the halfway subnormal fix:
x86_64: 514 -> 210
armhf: 304 -> 156 (v7 thumb, no vfma op)
arm: 400 -> 348 (soft float, no fenv)
round to odd paper (suggested by Sergey Davidoff):
[1] S. Boldo et al., Emulation of a FMA and correctly-rounded sums:
proved algorithms using rounding to odd, 2008
|
|
inexact halfway cases were not handled correctly for subnormals
fmaf(0x20201p-92f, 0x1fe01p-92f, 0x1p-130f)
= (float)(0x1p-130 + 0x1.000000004p-150)
was rounded to 0x1.00001p-130 first in double precision, then to
0x1p-130 in the float subnormal range instead of 0x1.00002p-130.
this is a minimal fix of the halfway check.
Reported-by: Sergey Davidoff <shnatsel@gmail.com>
|
|
TZif v1 encodes its version as NUL, but do_tzset treats only the byte
'1' as v1. It consequently reads a valid v1 file as if it contained a
second header.
Use zero and nonzero version bytes to distinguish v1 from later files.
|
|
stddef.h is unused, commit da88b16a221c9d327e1bfa61dd6f4f08dacce57a
removed the use of offsetof().
|
|
calling qsort() with a pointer to a function whose type is not
compatible with int(const void *, const void *) results in UB because
qsort() would call this function with an incompatible type.
avoid this by using qsort_r(). this is similar to how qsort() is
implemented on top of qsort_r().
the types of the pointers passed to wrapper_cmp() are
struct dirent *const * but the caller's comparison function expects
const struct dirent **. copy the pointer values into local variables
and pass their addresses to the caller's comparison function to get
the right type and avoid aliasing violations.
this is only necessary because the pointer to the comparison function
for scandir() was (incorrectly) specified as
int (*)(const struct dirent **, const struct dirent **) rather than
int (*)(struct dirent *const *, struct dirent *const *).
|
|
if the loop is exited because len * sizeof *names does not fit into
size_t, errno should be explicitly set to ENOMEM. previously, the
behavior differed depending on which value errno happened to have at
this point.
if cnt reached a value > INT_MAX, scandir() returned an incorrect
value. EOVERFLOW should be reported instead.
it's unlikely that these errors can actually occur. it may not even
be possible to have directories with that many entries, and even then
malloc() or realloc() will probably fail long before len or cnt reach
those large values.
|
|
opendir() or closedir() might act upon a cancellation request. because
scandir() did not disable cancellation or install a cancellation
cleanup handler, this could lead to memory and file descriptor leaks.
|
|
when closedir() set errno, scandir() misinterpreted this as a failure.
this was wrong for two reasons:
* if closedir() succeeds, errno could still have been set, e.g. by
__aio_close().
* even if closedir() "fails", it always closes the file descriptor and
frees memory, so there is no reason to free all directory entries
and return from scandir() with a failure.
|
|
POSIX.1-2024 requires that standard functions don't set errno to 0.
commit dae17a1aaf25d8333e729173d86659066607d87d ensured that cmp() and
the caller of scandir() cannot observe that errno is set to 0
internally. however, this was not yet the case for the sel() callback.
|
|
the standard allows but does not require detecting bad catalog
descriptors and reporting the as EBADF. detection is only possible in
the general case if nl_catd is its own resource identifier namespace
not shaed with address space or file descriptors or anything else;
however, (nl_catd)-1 is always detectable since it's reserved as an
error value, and reportedly all other implementations detect this
condition and just return the untranslated string. users of catgets,
including tcsh, rely on this.
|
|
(v)sprint() is supposed to return the number of bytes written to s,
excluding the terminating null byte. however, when these functions
return INT_MAX, only INT_MAX - 1 bytes (excluding the terminating null
byte) are written.
this is caused by the way vsprintf() is implemented: calling
vsnprintf() with n = INT_MAX. vsnprintf() returns the number of bytes
that would be written to s had n been sufficiently large excluding the
terminating null byte. output bytes beyond the n-1st are discarded.
to accommodate the largest strings (v)sprintf() can produce (length
INT_MAX, the return value is of type int), vsnprintf() has to be
called with n >= INT_MAX + 1.
calling vsnprintf() with n > INT_MAX is possible since commit
11fb383275d20f5f94c00425bd888a02ecbd218e.
|
|
expl asm special cased |x|>=16384 and used 2^trunc(x) then,
but this was wrong for x<=-16384 when 2^trunc(x) doesn't
underflow to 0. fixed by bumping the threshold up to 32768.
Reported-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
|
|
when x<0 and y is an odd int then powl is computed for -x first
then negated at the end. some overflow cases missed the negation:
powl(-1.5, 50001)
powl(-0.5, 50001)
powl(-0x1p-16444L, -1)
returned inf, 0 and inf instead of the negated values.
Reported-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
|
|
getword allocates the next expanded word before the result vector is
grown. If realloc fails, that word has not been stored in the vector and
cannot be reached by wordfree, so returning WRDE_NOSPACE leaks it.
Free the exclusively owned word before leaving the loop. Existing
partial results and the returned error are unchanged.
|
|
The ABI requires a stack frame to, at minimum, consist of the backchain slot and
the LR save slot at sp+0 and sp+4 respectively. The old code spilled r30/r31
into those slots, meaning that a backchain-based unwinder would see a nonsense
value as the backchain pointer and go on a wild goose chase.
It's admittedly a very small window where this is possible -- a thread that's
stopped in the middle of the clone() parent body -- but fixing it just requires
shifting the r30/r31 spill slots down by 8 bytes and storing the old sp in the
backchain slot, so seems reasonable to do.
|
|
It's a 32-bit pointer and passed on the stack; the upper 32 bits of the stack
slot are garbage. This works out fine if we're lucky and those bits happen to be
zeroed, but if they're not, we ask the kernel to write to some random 64-bit
location, which it will just silently fail to do (the process is in x32 mode;
nothing can be mapped up there), and consequently, we never learn the new
thread's tid.
|
|
at least gai_strerror() and regerror() are specified to accept any int
value. if the value was close to INT_MAX (for gai_strerror()) or
INT_MIN (for hstrerror() and regerror()) a signed integer overflow
would occur.
fix this by converting the int argument to unsigned before doing
arithmetic.
|
|
DNS query retry interval is calculated through timeout / attempts in
__res_msend_rc(), both are loaded from resolv.conf in
__get_resolv_conf(), while value of attempts isn't checked. This would
trigger an undefined behavior if attempts is set to zero in
configuration, causing misfunction or termination with SIGFPE.
Gracefully handle it by returning early.
|
|
commit cb0cdc2e88c652af225d2fc31c1dec99b9880d39 broke this as part of
future proofing.
|
|
this fixes a build regression for riscv32 introduced in commit
b306b16af15c89a04d8e0c55cac2dadbeb39c083. prior to that, the riscv32
bits/syscall.h.in defined a macro for the nanosleep syscall, despite
the kernel on time64-native archs having no such syscall.
our clock_nanosleep uses the old nanosleep syscall when possible as
part of minimal compatibility with pre-2.6 kernels. using a
non-functional syscall number didn't have any ill effect on riscv32 or
future time64-native archs, since the affected code is unreachable in
that case, but removing the wrongly defined macro broke the build.
this change fixes it.
in order not to need to fix this again if future 64-bit archs also
drop the old nanosleep syscall factor out the conditional use of
SYS_nanosleep and use the same approach in the preprocessor else block
for them.
|
|
ftello adds pending buffered output to the position reported by the
underlying seek operation. Near LLONG_MAX, the addition can overflow
signed off_t and return an apparently successful negative position.
Check that the buffered-byte count fits before adding it. Fail with
EOVERFLOW when the logical position cannot be represented.
|
|
For SEEK_CUR, fseeko subtracts the unread input-buffer length from the
caller's offset before invoking the underlying seek operation. A valid
LLONG_MIN offset therefore overflows before the seek can reject the
unrepresentable logical result.
Detect the underflow and fail with EOVERFLOW without flushing or
discarding the stream's buffers.
|
|
mktime is required to accept and normalize out-of-range members of
struct tm. When tm_mday is INT_MIN, subtracting one from it overflows
before the existing long long multiplication takes effect.
Perform the subtraction in long long so the complete int range can be
normalized as intended.
|
|
Fresh writable streams use null wpos and wend pointers until output is
initialized. The non-ASCII path adds MB_LEN_MAX to wpos before comparing
it with wend, which is invalid for a null pointer. The addition can also
form a pointer beyond one past the buffer when little space remains.
First require an active output buffer. Then compare the defined
difference between its pointers. Preserve the existing strict capacity
test and use the normal write fallback otherwise.
|
|
|
|
acosh(-0x1.8p15) returned -3.7534177368329567 instead of nan.
the same issue got fixed for acoshf and acoshl in commits
c4c38e6364323b6d83ba3428464e19987b981d7a and
6d10102709df4bc966d2846c1c45cd667e5048e5 here we follow the latter.
reported by Paul Zimmermann.
|
|
since commit e1a51185ceb4386481491e11f6dd39569b9e54f7, popen obeys an
obscure historical requirement to implement a sort of pseudo-cloexec
behavior for other pipe streams obtained by popen. but since popen
uses posix_spawn (and thereby posix_spawn file actions) internally,
the time of check for other pipe streams is separated from the time of
closure.
this was intended to be addressed by popen holding the open file list
lock across posix_spawn, but pclose (via fclose) closes the file
descriptor before taking the open file list lock, only using the lock
for updating the linked list pointers. this is to avoid serializing
fclose operations across the entire process, since in general close
may be a blocking operation.
multiple solutions to this problem were considered, but the simplest
and least invasive is conditionally taking the open file list lock
early for popen streams -- that is, for FILE streams where the
pipe_pid member is nonzero. since the file descriptor refers to a
pipe, closing it is a simple, nonblocking operation, and the only cost
is the time spent entering and leaving kernelspace while the lock is
held.
since individual FILE locks cannot be held while taking the open file
list lock (this would violate lock order protocol and produce
deadlocks), the FILE lock must be released after fflush but before the
ofl lock is taken. there is no point in retaking the lock afterwards,
since the FILE pointer is no longer valid and any further use by the
application would be undefined. so, simply let fflush do the locking.
note that the early return path (F_PERM) is not reachable for popen
streams, only for stdin/stdout/stderr, which are always normal FILEs.
thus, it does not provide a code path to return with the ofl lock
still held.
|
|
the namespace-safety remappings in glue.h handled mmap, madvise, and
mremap correctly but somehow overlooked munmap and mprotect.
|
|
LDBL_* macros were not defined in logbl.
the code happens to be correct without them, but when the long double
format matches double the intention was to tail call logb.
|
|
the expression LDBL_MANT_DIG/4+1 was intended to represent the number
of hex digits which can be significant, after which all that matters
to the result, regardless of rounding mode, is whether any part of the
tail is nonzero.
however, the expression LDBL_MANT_DIG/4 is only exact for ld80 archs.
for ld64 and ld128, the truncation of the remainder caused one too few
digits to be processed, producing incorrect rounding.
for ld128 archs, only strtold and scanf's %La conversion specifier
were affected; doubles and floats still had plenty of trailing digits
to yield a correct final rounding. but for ld64 archs, the number of
digits processed were insufficient for double, and could affect any
code using strtod or scanf's %a.
for ld64 archs, 0x1.111111111111281 produces an incorrect rounding
down, and 0x1.11111111111111 produces an incorrect rounding up.
for ld128 archs, the inputs 0x1.111111111111111111111111111281 and
0x1.11111111111111111111111111111 behave respectively.
rounding up in the expression for the number of hex digits needed
produces correct results.
|
|
aligned allocations are handled by over-allocating enough to ensure an
aligned subrange exists and framing the usable space to that subrange.
the framing can only handle offsets up to a 32-bit multiple of the
allocation UNIT (16 bytes), and aligned_alloc correctly checks for and
rejects larger alignments.
however, when get_meta reads back the offset, the type of the variable
and everything else in the expression where it's used was int, not
size_t, and offset*UNIT can overflow. modulo the "anything can happen"
aspect of overflow being undefined, a clean trap will occur and the
program will terminate. this would happen on any call to free,
realloc, or malloc_usable_size call on the large-alignment object.
switch the type of offset in get_meta from int to size_t. this has
been checked not to break any of the subsequent assertions:
- assert(offset > 0xffff) was wrongly rejecting offsets that would be
interpreted as negative when converted to signed int. this is fixed
by processing offset as unsigned.
- the check against the slot boundaries switches which assert would
catch values that were previously interpreted as negative, but the
net effect is the same.
- the check against maplen was already converting to unsigned long due
to the 4096UL in the expression. in doing so, it was incorrectly
sign-extending the offset rather than zero-extending. this is fixed
by using unsigned type to begin with.
in addition, take the opportunity to trap on offsets were offset*UNIT
would overflow. this cannot happen on 64-bit archs (and it should be
optimized out by the compiler there), but it's an additional signal we
can use to catch out-of-bounds writes on 32-bit ones. and the check
only happens when operating on extremely large, overaligned objects,
so the relative cost of checking is essentially zero.
|
|
commit d2e061a2bd3f7674cfef2e2217e0695419041b5e wrongly added this
case based on a misreading of the standard text regarding null
termination in write/update modes. apparently, the condition "if it
fits" was interpreted as only applying to update modes, despite the
words "or for writing only" appearing.
|
|
|
|
if shl() or shr() are called with n==8*sizeof(size_t), n is adjusted
to 0. the shift by (sizeof(size_t) * 8 - n) that then follows will
consequently shift by the width of size_t, which is UB and in practice
produces an incorrect result.
return early in this case. the bitvector p was already shifted by the
required amount.
|
|
while the root cause of CVE-2026-40200 was a faulty ctz primitive, the
fallout of the bug would have been limited to erroneous sorting or
infinite loop if not for the stores to a stack-based array that
depended on trusting invariants in order not to go out of bounds.
increase the size of the array to a power of two so that we can mask
indices into it to force them into range. in the absence of any
further bug, the masking is a no-op, but it does not have any
measurable performance cost, and it makes spatial memory safety
trivial to prove (and for readers not familiar with the algorithms to
trust).
|
|
the pntz function, implementing a "count trailing zeros" variant for a
bit vector consisting of two size_t words, erroneously returned zero
rather than the number of bits in the low word when the first bit set
was the low bit of the high word.
as a result, a loop in the trinkle function which should have a
guaranteed small bound on the number of iterations, could run
unboundedly, thereby overflowing a stack-based working-space array
which was sized for the bound.
CVE-2026-40200 has been assigned for this issue.
|
|
use of || forces the caller to boolean-normalize the result of
iswalpha to 0 or 1, requiring code after the call returns and thus
precluding a tail call.
since this isn't actually needed, don't write it that way.
|
|
in order to implement the "UTF" aspect of gb18030 (ability to
represent arbitrary unicode characters not present in the 2-byte
mapping), we have to apply the index obtained from the encoded 4-byte
sequence into the set of unmapped characters. this was done by
scanning repeatedly over the table of mapped characters and counting
off mapped characters below a running index by which to adjust the
running index by on each iteration. this iterative process eventually
leaves us with the value of the Nth unmapped character replacing the
index, but depending on which particular character that is, the number
of iterations needed to find it can be in the tens of thousands, and
each iteration traverses the whole 126x190 table in the inner loop.
this can lead to run times exceeding an entire second per character on
moderate-speed machines.
on top of that, the transformation logic produced wrong results for
BMP characters above the the surrogate range, as a result of not
correctly accounting for it being excluded, and for characters outside
the BMP, as a result of a misunderstanding of how gb18030 encodes
them.
this patch replaces the unmapped character lookup with a single linear
search of a list of unmapped ranges. there are only 206 such ranges,
and these are permanently assigned and unchangeable as a consequence
of the character encoding having to be stable, so a simple array of
16-bit start/length values for each range consumes only 824 bytes, a
very reasonable size cost here.
this new table accounts for the previously-incorrect surrogate
handling, and non-BMP characters are handled correctly by a single
offset, without the need for any unmapped-range search.
there are still a small number of mappings that are incorrect due to
late changes made in the definition of gb18030, swapping PUA
codepoints with proper Unicode characters. correcting these requires a
postprocessing step that will be added later.
|
|
in BRE \n matches the nth subexpression, but regcomp did not check if
the nth subexpression was complete or not, only that there were more
subexpressions overall than the largest backref.
fix regcomp to error if the referenced subexpression is incomplete.
the bug could cause an infinite loop in regexec:
regcomp(&re, "\\(^a*\\1\\)*", 0);
regexec(&re, "aa", 0, 0, 0);
since BRE has backreferences, any application accepting a BRE from
untrusted sources is already vulnerable to an attacker-controlled
near-infinite (exponential-time) loop, but this particular case where
the loop is actually infinite can and should be avoided.
ERE is not affected since the language an ERE describes is actually
regular.
Reported-by: Simon Resch <simon.resch@code-intelligence.com>
|
|
there are three issues here:
1. if tzset has not been called (explicitly or implicitly), the
tzname[] array will contain null pointers, and the dereference to
compare against them has undefined behavior (and will fault).
2. access to tzname[] was performed without the timezone lock held.
this resulted in a data race if the timezone is concurrently changed
from another thread.
3. due to unintended signedness of the types, the open-coded isalpha
in the non-matching case was wrong and would continue past null
termination.
to fix the first two issues, the body of the %Z conversion is moved to
__tz.c where it has access to locking, and null checks are added.
there is probably an argument to be made that the equivalent of tzset
should happen here, but POSIX does not specify that to happen, so in
the absence of an interpretation adding such an allowance or
requirement, it is not done.
the third issue is fixed just by using the existing isalpha macro.
|