musl: backport various post-1.1.15 fixes

Backport most important fixes up to latest HEAD

- Taken post-commit reverts/fixes into account

Compile tested
Run-tested on cns3xxx & imx6 targets

Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
lede-17.01
Koen Vandeputte 2016-12-22 17:17:04 +01:00 committed by Felix Fietkau
parent b97c933ffb
commit 2912f9f2a2
26 changed files with 1513 additions and 0 deletions

View File

@ -0,0 +1,41 @@
From 6399fa9d29ea83de4735680b77d457bd59606532 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 7 Jul 2016 16:51:37 -0400
Subject: fix asctime day/month names not to vary by locale
the FIXME comment here was overlooked at the time locale support was
added.
---
src/time/__asctime.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/time/__asctime.c b/src/time/__asctime.c
index e7e7f07..f114dfe 100644
--- a/src/time/__asctime.c
+++ b/src/time/__asctime.c
@@ -1,17 +1,16 @@
#include <time.h>
#include <stdio.h>
#include <langinfo.h>
+#include "locale_impl.h"
#include "atomic.h"
-const char *__nl_langinfo(nl_item);
+const char *__nl_langinfo_l(nl_item, locale_t);
char *__asctime(const struct tm *restrict tm, char *restrict buf)
{
- /* FIXME: change __nl_langinfo to __nl_langinfo_l with explicit C
- * locale once we have locales */
if (snprintf(buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
- __nl_langinfo(ABDAY_1+tm->tm_wday),
- __nl_langinfo(ABMON_1+tm->tm_mon),
+ __nl_langinfo_l(ABDAY_1+tm->tm_wday, C_LOCALE),
+ __nl_langinfo_l(ABMON_1+tm->tm_mon, C_LOCALE),
tm->tm_mday, tm->tm_hour,
tm->tm_min, tm->tm_sec,
1900 + tm->tm_year) >= 26)
--
cgit v0.11.2

View File

@ -0,0 +1,71 @@
From 7cc3a28eed7e3b72a1ce4568fb55154bb0540726 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 11 Aug 2016 18:36:46 -0400
Subject: fix pread/pwrite syscall calling convention on sh
despite sh not generally using register-pair alignment for 64-bit
syscall arguments, there are arch-specific versions of the syscall
entry points for pread and pwrite which include a dummy argument for
alignment before the 64-bit offset argument.
---
arch/sh/syscall_arch.h | 1 +
src/internal/syscall.h | 4 ++++
src/unistd/pread.c | 2 +-
src/unistd/pwrite.c | 2 +-
4 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/sh/syscall_arch.h b/arch/sh/syscall_arch.h
index f63675a..84758fe 100644
--- a/arch/sh/syscall_arch.h
+++ b/arch/sh/syscall_arch.h
@@ -2,6 +2,7 @@
((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
((union { long long ll; long l[2]; }){ .ll = x }).l[1]
#define __SYSCALL_LL_O(x) __SYSCALL_LL_E((x))
+#define __SYSCALL_LL_PRW(x) 0, __SYSCALL_LL_E((x))
/* The extra OR instructions are to work around a hardware bug:
* http://documentation.renesas.com/doc/products/mpumcu/tu/tnsh7456ae.pdf
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index ff3cf53..6d378a8 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -12,6 +12,10 @@
#define SYSCALL_MMAP2_UNIT 4096ULL
#endif
+#ifndef __SYSCALL_LL_PRW
+#define __SYSCALL_LL_PRW(x) __SYSCALL_LL_O(x)
+#endif
+
#ifndef __scc
#define __scc(X) ((long) (X))
typedef long syscall_arg_t;
diff --git a/src/unistd/pread.c b/src/unistd/pread.c
index 3d2799f..5483eb9 100644
--- a/src/unistd/pread.c
+++ b/src/unistd/pread.c
@@ -4,7 +4,7 @@
ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
{
- return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_O(ofs));
+ return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs));
}
LFS64(pread);
diff --git a/src/unistd/pwrite.c b/src/unistd/pwrite.c
index bbe4c34..4bf3d7d 100644
--- a/src/unistd/pwrite.c
+++ b/src/unistd/pwrite.c
@@ -4,7 +4,7 @@
ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
{
- return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_O(ofs));
+ return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_PRW(ofs));
}
LFS64(pwrite);
--
cgit v0.11.2

View File

@ -0,0 +1,49 @@
From 0a950dcf15bb9f7274c804dca490e9e20e475f3e Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Sat, 20 Aug 2016 21:04:31 +0200
Subject: verify that ttyname refers to the same file as the fd
linux containers use separate mount namespace so the /proc
symlink might not point to the right device if the fd was
opened in the parent namespace, in this case return ENOENT.
---
src/unistd/ttyname_r.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/src/unistd/ttyname_r.c b/src/unistd/ttyname_r.c
index 8bac7b2..a38ba4f 100644
--- a/src/unistd/ttyname_r.c
+++ b/src/unistd/ttyname_r.c
@@ -1,10 +1,12 @@
#include <unistd.h>
#include <errno.h>
+#include <sys/stat.h>
void __procfdname(char *, unsigned);
int ttyname_r(int fd, char *name, size_t size)
{
+ struct stat st1, st2;
char procname[sizeof "/proc/self/fd/" + 3*sizeof(int) + 2];
ssize_t l;
@@ -15,8 +17,13 @@ int ttyname_r(int fd, char *name, size_t size)
if (l < 0) return errno;
else if (l == size) return ERANGE;
- else {
- name[l] = 0;
- return 0;
- }
+
+ name[l] = 0;
+
+ if (stat(name, &st1) || fstat(fd, &st2))
+ return errno;
+ if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
+ return ENOENT;
+
+ return 0;
}
--
cgit v0.11.2

View File

@ -0,0 +1,25 @@
From c1f4ed150137d793c9d07356305a89e8785e7e02 Mon Sep 17 00:00:00 2001
From: Duncan Overbruck <duncaen@voidlinux.eu>
Date: Thu, 18 Aug 2016 17:06:16 +0200
Subject: fix FFSYNC by changing it to O_SYNC
O_FSYNC was never defined and is legacy/wrong, nothing seems to use it.
---
include/fcntl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/fcntl.h b/include/fcntl.h
index e683e4d..0e165ca 100644
--- a/include/fcntl.h
+++ b/include/fcntl.h
@@ -99,7 +99,7 @@ int posix_fallocate(int, off_t, off_t);
#define AT_EMPTY_PATH 0x1000
#define FAPPEND O_APPEND
-#define FFSYNC O_FSYNC
+#define FFSYNC O_SYNC
#define FASYNC O_ASYNC
#define FNONBLOCK O_NONBLOCK
#define FNDELAY O_NDELAY
--
cgit v0.11.2

View File

@ -0,0 +1,31 @@
From 78897b0dc00b7cd5c29af5e0b7eebf2396d8dce0 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Fri, 16 Sep 2016 17:40:08 -0400
Subject: fix printf regression with alt-form octal, zero flag, and field width
commit b91cdbe2bc8b626aa04dc6e3e84345accf34e4b1, in fixing another
issue, changed the logic for how alt-form octal adds the leading zero
to adjust the precision rather than using a prefix character. this
wrongly suppressed the zero flag by mimicing an explicit precision
given by the format string. switch back to using a prefix character.
based on bug report and patch by Dmitry V. Levin, but simplified.
---
src/stdio/vfprintf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 2ecf769..e439a07 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -570,7 +570,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
if (0) {
case 'o':
a = fmt_o(arg.i, z);
- if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
+ if ((fl&ALT_FORM) && p<z-a+1) prefix+=5, pl=1;
} if (0) {
case 'd': case 'i':
pl=1;
--
cgit v0.11.2

View File

@ -0,0 +1,35 @@
From 3848a99f65952a77c03bbd905cae988f37f13ea6 Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogalcc@gmail.com>
Date: Fri, 16 Sep 2016 13:34:24 -0400
Subject: fix ifru_data and ifcu_buf types in net/if.h
glibc, freebsd, and openbsd use character pointers (caddr_t) for
these fields. only linux uses void pointer for the ifru_data type.
---
include/net/if.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/net/if.h b/include/net/if.h
index 1a4059d..2f2fcc1 100644
--- a/include/net/if.h
+++ b/include/net/if.h
@@ -89,7 +89,7 @@ struct ifreq {
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
- void *ifru_data;
+ char *ifru_data;
} ifr_ifru;
};
@@ -116,7 +116,7 @@ struct ifreq {
struct ifconf {
int ifc_len;
union {
- void *ifcu_buf;
+ char *ifcu_buf;
struct ifreq *ifcu_req;
} ifc_ifcu;
};
--
cgit v0.11.2

View File

@ -0,0 +1,36 @@
From 32055d52ca43d867d6dbb763dc5213a8d3536a23 Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogalcc@gmail.com>
Date: Thu, 15 Sep 2016 11:27:30 -0400
Subject: fix if_indextoname error case
posix requires errno to be set to ENXIO if the interface does not exist.
linux returns ENODEV instead so we handle this.
---
src/network/if_indextoname.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/network/if_indextoname.c b/src/network/if_indextoname.c
index 6ee7f13..3b368bf 100644
--- a/src/network/if_indextoname.c
+++ b/src/network/if_indextoname.c
@@ -3,6 +3,7 @@
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <string.h>
+#include <errno.h>
#include "syscall.h"
char *if_indextoname(unsigned index, char *name)
@@ -14,5 +15,9 @@ char *if_indextoname(unsigned index, char *name)
ifr.ifr_ifindex = index;
r = ioctl(fd, SIOCGIFNAME, &ifr);
__syscall(SYS_close, fd);
- return r < 0 ? 0 : strncpy(name, ifr.ifr_name, IF_NAMESIZE);
+ if (r < 0) {
+ if (errno == ENODEV) errno = ENXIO;
+ return 0;
+ }
+ return strncpy(name, ifr.ifr_name, IF_NAMESIZE);
}
--
cgit v0.11.2

View File

@ -0,0 +1,38 @@
From 5505f6afae9acf37ef565c68a07ca3df7b1ae2cb Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogalcc@gmail.com>
Date: Fri, 9 Sep 2016 21:23:17 -0400
Subject: add missing *_unlocked and wcsftime_l prototypes to wchar.h
these functions had been implemented, but prototypes were not made available
---
include/wchar.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/include/wchar.h b/include/wchar.h
index 0167dce..3e6db5f 100644
--- a/include/wchar.h
+++ b/include/wchar.h
@@ -136,6 +136,21 @@ size_t wcsftime (wchar_t *__restrict, size_t, const wchar_t *__restrict, const s
#undef iswdigit
+#if defined(_GNU_SOURCE)
+wint_t fgetwc_unlocked (FILE *);
+wint_t getwc_unlocked (FILE *);
+wint_t getwchar_unlocked (void);
+wint_t fputwc_unlocked (wchar_t, FILE *);
+wint_t putwc_unlocked (wchar_t, FILE *);
+wint_t putwchar_unlocked (wchar_t);
+wchar_t *fgetws_unlocked (wchar_t *__restrict, int, FILE *__restrict);
+int fputws_unlocked (const wchar_t *__restrict, FILE *__restrict);
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+size_t wcsftime_l (wchar_t *__restrict, size_t, const wchar_t *__restrict, const struct tm *__restrict, locale_t);
+#endif
+
#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
|| defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
FILE *open_wmemstream(wchar_t **, size_t *);
--
cgit v0.11.2

View File

@ -0,0 +1,43 @@
From 66570ec9c465e3c6c5d6dbd7dd42e45041a39288 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 19 Sep 2016 11:15:51 -0400
Subject: fix undefined behavior in sched.h cpu_set_t usage
since cpu sets can be dynamically allocated and have variable size,
accessing their contents via ->__bits is not valid; performing pointer
arithmetic outside the range of the size of the declared __bits array
results in undefined beahavior. instead, only use cpu_set_t for
fixed-size cpu set objects (instantiated by the caller) and as an
abstract pointer type for dynamically allocated ones. perform all
accesses simply by casting the abstract pointer type cpuset_t * back
to unsigned long *.
---
include/sched.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/sched.h b/include/sched.h
index af82d6c..d1cccb7 100644
--- a/include/sched.h
+++ b/include/sched.h
@@ -82,7 +82,7 @@ int sched_getaffinity(pid_t, size_t, cpu_set_t *);
int sched_setaffinity(pid_t, size_t, const cpu_set_t *);
#define __CPU_op_S(i, size, set, op) ( (i)/8U >= (size) ? 0 : \
- ((set)->__bits[(i)/8/sizeof(long)] op (1UL<<((i)%(8*sizeof(long))))) )
+ (((unsigned long *)(set))[(i)/8/sizeof(long)] op (1UL<<((i)%(8*sizeof(long))))) )
#define CPU_SET_S(i, size, set) __CPU_op_S(i, size, set, |=)
#define CPU_CLR_S(i, size, set) __CPU_op_S(i, size, set, &=~)
@@ -94,8 +94,8 @@ static __inline void __CPU_##func##_S(size_t __size, cpu_set_t *__dest, \
{ \
size_t __i; \
for (__i=0; __i<__size/sizeof(long); __i++) \
- __dest->__bits[__i] = __src1->__bits[__i] \
- op __src2->__bits[__i] ; \
+ ((unsigned long *)__dest)[__i] = ((unsigned long *)__src1)[__i] \
+ op ((unsigned long *)__src2)[__i] ; \
}
__CPU_op_func_S(AND, &)
--
cgit v0.11.2

View File

@ -0,0 +1,41 @@
From 8d7a3f40c8de414122eb8eb2131291782ee8ed15 Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogalcc@gmail.com>
Date: Fri, 23 Sep 2016 21:10:07 -0400
Subject: fix getservby*_r result pointer value on error
this is a clone of the fix to the gethostby*_r functions in
commit fe82bb9b921be34370e6b71a1c6f062c20999ae0. the man pages
document that the getservby*_r functions set this pointer to
NULL if there was an error or if no record was found.
---
src/network/getservbyname_r.c | 2 ++
src/network/getservbyport_r.c | 1 +
2 files changed, 3 insertions(+)
diff --git a/src/network/getservbyname_r.c b/src/network/getservbyname_r.c
index 056c2f3..ad3d616 100644
--- a/src/network/getservbyname_r.c
+++ b/src/network/getservbyname_r.c
@@ -15,6 +15,8 @@ int getservbyname_r(const char *name, const char *prots,
struct service servs[MAXSERVS];
int cnt, proto, align;
+ *res = 0;
+
/* Align buffer */
align = -(uintptr_t)buf & ALIGN-1;
if (buflen < 2*sizeof(char *)+align)
diff --git a/src/network/getservbyport_r.c b/src/network/getservbyport_r.c
index a0a7cae..0ae0e41 100644
--- a/src/network/getservbyport_r.c
+++ b/src/network/getservbyport_r.c
@@ -20,6 +20,7 @@ int getservbyport_r(int port, const char *prots,
if (r) r = getservbyport_r(port, "udp", se, buf, buflen, res);
return r;
}
+ *res = 0;
/* Align buffer */
i = (uintptr_t)buf & sizeof(char *)-1;
--
cgit v0.11.2

View File

@ -0,0 +1,23 @@
From 583ea83541dcc6481c7a1bd1a9b485526bad84a1 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Tue, 4 Oct 2016 17:14:57 +0000
Subject: fix strftime %y for negative tm_year
---
src/time/strftime.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/time/strftime.c b/src/time/strftime.c
index f1ccc4d..e103e02 100644
--- a/src/time/strftime.c
+++ b/src/time/strftime.c
@@ -167,6 +167,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
goto nl_strftime;
case 'y':
val = tm->tm_year % 100;
+ if (val<0) val += 100;
goto number;
case 'Y':
val = tm->tm_year + 1900LL;
--
cgit v0.11.2

View File

@ -0,0 +1,72 @@
From c3edc06d1e1360f3570db9155d6b318ae0d0f0f7 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 6 Oct 2016 18:34:58 -0400
Subject: fix missing integer overflow checks in regexec buffer size
computations
most of the possible overflows were already ruled out in practice by
regcomp having already succeeded performing larger allocations.
however at least the num_states*num_tags multiplication can clearly
overflow in practice. for safety, check them all, and use the proper
type, size_t, rather than int.
also improve comments, use calloc in place of malloc+memset, and
remove bogus casts.
---
src/regex/regexec.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/regex/regexec.c b/src/regex/regexec.c
index 16c5d0a..dd52319 100644
--- a/src/regex/regexec.c
+++ b/src/regex/regexec.c
@@ -34,6 +34,7 @@
#include <wchar.h>
#include <wctype.h>
#include <limits.h>
+#include <stdint.h>
#include <regex.h>
@@ -206,11 +207,24 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
/* Allocate memory for temporary data required for matching. This needs to
be done for every matching operation to be thread safe. This allocates
- everything in a single large block from the stack frame using alloca()
- or with malloc() if alloca is unavailable. */
+ everything in a single large block with calloc(). */
{
- int tbytes, rbytes, pbytes, xbytes, total_bytes;
+ size_t tbytes, rbytes, pbytes, xbytes, total_bytes;
char *tmp_buf;
+
+ /* Ensure that tbytes and xbytes*num_states cannot overflow, and that
+ * they don't contribute more than 1/8 of SIZE_MAX to total_bytes. */
+ if (num_tags > SIZE_MAX/(8 * sizeof(int) * tnfa->num_states))
+ goto error_exit;
+
+ /* Likewise check rbytes. */
+ if (tnfa->num_states+1 > SIZE_MAX/(8 * sizeof(*reach_next)))
+ goto error_exit;
+
+ /* Likewise check pbytes. */
+ if (tnfa->num_states > SIZE_MAX/(8 * sizeof(*reach_pos)))
+ goto error_exit;
+
/* Compute the length of the block we need. */
tbytes = sizeof(*tmp_tags) * num_tags;
rbytes = sizeof(*reach_next) * (tnfa->num_states + 1);
@@ -221,10 +235,9 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
+ (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes;
/* Allocate the memory. */
- buf = xmalloc((unsigned)total_bytes);
+ buf = calloc(total_bytes, 1);
if (buf == NULL)
return REG_ESPACE;
- memset(buf, 0, (size_t)total_bytes);
/* Get the various pointers within tmp_buf (properly aligned). */
tmp_tags = (void *)buf;
--
cgit v0.11.2

View File

@ -0,0 +1,189 @@
From aee6abb2400b9a955c2b41166db1c22f63ad42ef Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 6 Oct 2016 12:15:47 -0400
Subject: fix regexec with haystack strings longer than INT_MAX
we inherited from TRE regexec code that's utterly wrong with respect
to the integer types it's using. while it doesn't appear that
compilers are producing unsafe output, signed integer overflows seem
to happen, and regexec fails to find matches past offset INT_MAX.
this patch fixes the type of all variables/fields used to store
offsets in the string from int to regoff_t. after the changes, basic
testing showed that regexec can now find matches past 2GB (INT_MAX)
and past 4GB on x86_64, and code generation is unchanged on i386.
---
src/regex/regexec.c | 54 +++++++++++++++++++++++++++--------------------------
1 file changed, 28 insertions(+), 26 deletions(-)
diff --git a/src/regex/regexec.c b/src/regex/regexec.c
index dd52319..5c4cb92 100644
--- a/src/regex/regexec.c
+++ b/src/regex/regexec.c
@@ -44,7 +44,7 @@
static void
tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
- const tre_tnfa_t *tnfa, int *tags, int match_eo);
+ const tre_tnfa_t *tnfa, regoff_t *tags, regoff_t match_eo);
/***********************************************************************
from tre-match-utils.h
@@ -97,7 +97,7 @@ tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
/* Returns 1 if `t1' wins `t2', 0 otherwise. */
static int
tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions,
- int *t1, int *t2)
+ regoff_t *t1, regoff_t *t2)
{
int i;
for (i = 0; i < num_tags; i++)
@@ -157,25 +157,25 @@ tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase)
typedef struct {
tre_tnfa_transition_t *state;
- int *tags;
+ regoff_t *tags;
} tre_tnfa_reach_t;
typedef struct {
- int pos;
- int **tags;
+ regoff_t pos;
+ regoff_t **tags;
} tre_reach_pos_t;
static reg_errcode_t
tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
- int *match_tags, int eflags,
- int *match_end_ofs)
+ regoff_t *match_tags, int eflags,
+ regoff_t *match_end_ofs)
{
/* State variables required by GET_NEXT_WCHAR. */
tre_char_t prev_c = 0, next_c = 0;
const char *str_byte = string;
- int pos = -1;
- int pos_add_next = 1;
+ regoff_t pos = -1;
+ regoff_t pos_add_next = 1;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
@@ -191,10 +191,10 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
int *tag_i;
int num_tags, i;
- int match_eo = -1; /* end offset of match (-1 if no match found yet) */
+ regoff_t match_eo = -1; /* end offset of match (-1 if no match found yet) */
int new_match = 0;
- int *tmp_tags = NULL;
- int *tmp_iptr;
+ regoff_t *tmp_tags = NULL;
+ regoff_t *tmp_iptr;
#ifdef TRE_MBSTATE
memset(&mbstate, '\0', sizeof(mbstate));
@@ -214,7 +214,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
/* Ensure that tbytes and xbytes*num_states cannot overflow, and that
* they don't contribute more than 1/8 of SIZE_MAX to total_bytes. */
- if (num_tags > SIZE_MAX/(8 * sizeof(int) * tnfa->num_states))
+ if (num_tags > SIZE_MAX/(8 * sizeof(regoff_t) * tnfa->num_states))
goto error_exit;
/* Likewise check rbytes. */
@@ -229,7 +229,7 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string,
tbytes = sizeof(*tmp_tags) * num_tags;
rbytes = sizeof(*reach_next) * (tnfa->num_states + 1);
pbytes = sizeof(*reach_pos) * tnfa->num_states;
- xbytes = sizeof(int) * num_tags;
+ xbytes = sizeof(regoff_t) * num_tags;
total_bytes =
(sizeof(long) - 1) * 4 /* for alignment paddings */
+ (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes;
@@ -490,12 +490,12 @@ error_exit:
*/
typedef struct {
- int pos;
+ regoff_t pos;
const char *str_byte;
tre_tnfa_transition_t *state;
int state_id;
int next_c;
- int *tags;
+ regoff_t *tags;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
@@ -591,13 +591,13 @@ typedef struct tre_backtrack_struct {
static reg_errcode_t
tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
- int *match_tags, int eflags, int *match_end_ofs)
+ regoff_t *match_tags, int eflags, regoff_t *match_end_ofs)
{
/* State variables required by GET_NEXT_WCHAR. */
tre_char_t prev_c = 0, next_c = 0;
const char *str_byte = string;
- int pos = 0;
- int pos_add_next = 1;
+ regoff_t pos = 0;
+ regoff_t pos_add_next = 1;
#ifdef TRE_MBSTATE
mbstate_t mbstate;
#endif /* TRE_MBSTATE */
@@ -610,15 +610,16 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
started from. */
int next_c_start;
const char *str_byte_start;
- int pos_start = -1;
+ regoff_t pos_start = -1;
#ifdef TRE_MBSTATE
mbstate_t mbstate_start;
#endif /* TRE_MBSTATE */
/* End offset of best match so far, or -1 if no match found yet. */
- int match_eo = -1;
+ regoff_t match_eo = -1;
/* Tag arrays. */
- int *next_tags, *tags = NULL;
+ int *next_tags;
+ regoff_t *tags = NULL;
/* Current TNFA state. */
tre_tnfa_transition_t *state;
int *states_seen = NULL;
@@ -768,8 +769,9 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
/* This is a back reference state. All transitions leaving from
this state have the same back reference "assertion". Instead
of reading the next character, we match the back reference. */
- int so, eo, bt = trans_i->u.backref;
- int bt_len;
+ regoff_t so, eo;
+ int bt = trans_i->u.backref;
+ regoff_t bt_len;
int result;
/* Get the substring we need to match against. Remember to
@@ -926,7 +928,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
endpoint values. */
static void
tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
- const tre_tnfa_t *tnfa, int *tags, int match_eo)
+ const tre_tnfa_t *tnfa, regoff_t *tags, regoff_t match_eo)
{
tre_submatch_data_t *submatch_data;
unsigned int i, j;
@@ -996,7 +998,7 @@ regexec(const regex_t *restrict preg, const char *restrict string,
{
tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD;
reg_errcode_t status;
- int *tags = NULL, eo;
+ regoff_t *tags = NULL, eo;
if (tnfa->cflags & REG_NOSUB) nmatch = 0;
if (tnfa->num_tags > 0 && nmatch > 0)
{
--
cgit v0.11.2

View File

@ -0,0 +1,35 @@
From 70d2687d85c314963cf280759b23fd4573ff0d82 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Wed, 19 Oct 2016 20:17:16 -0400
Subject: fix integer overflow in float printf needed-precision computation
if the requested precision is close to INT_MAX, adding
LDBL_MANT_DIG/3+8 overflows. in practice the resulting undefined
behavior manifests as a large negative result, which is then used to
compute the new end pointer (z) with a wildly out-of-bounds value
(more overflow, more undefined behavior). the end result is at least
incorrect output and character count (return value); worse things do
not seem to happen, but detailed analysis has not been done.
this patch fixes the overflow by performing the intermediate
computation as unsigned; after division by 9, the final result
necessarily fits in int.
---
src/stdio/vfprintf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index e439a07..cd17ad7 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -312,7 +312,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
}
while (e2<0) {
uint32_t carry=0, *b;
- int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3+8)/9;
+ int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9;
for (d=a; d<z; d++) {
uint32_t rm = *d & (1<<sh)-1;
*d = (*d>>sh) + carry;
--
cgit v0.11.2

View File

@ -0,0 +1,390 @@
From 167dfe9672c116b315e72e57a55c7769f180dffa Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 20 Oct 2016 00:22:09 -0400
Subject: fix integer overflows and uncaught EOVERFLOW in printf core
this patch fixes a large number of missed internal signed-overflow
checks and errors in determining when the return value (output length)
would exceed INT_MAX, which should result in EOVERFLOW. some of the
issues fixed were reported by Alexander Cherepanov; others were found
in subsequent review of the code.
aside from the signed overflows being undefined behavior, the
following specific bugs were found to exist in practice:
- overflows computing length of floating point formats with huge
explicit precisions, integer formats with prefix characters and huge
explicit precisions, or string arguments or format strings longer
than INT_MAX, resulted in wrong return value and wrong %n results.
- literal width and precision values outside the range of int were
misinterpreted, yielding wrong behavior in at least one well-defined
case: string formats with precision greater than INT_MAX were
sometimes truncated.
- in cases where EOVERFLOW is produced, incorrect values could be
written for %n specifiers past the point of exceeding INT_MAX.
in addition to fixing these bugs, we now stop producing output
immediately when output length would exceed INT_MAX, rather than
continuing and returning an error only at the end.
---
src/stdio/vfprintf.c | 72 +++++++++++++++++++++++++++++++++++----------------
src/stdio/vfwprintf.c | 63 +++++++++++++++++++++++++++-----------------
2 files changed, 89 insertions(+), 46 deletions(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index cd17ad7..e2ab2dc 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -272,6 +272,8 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
} while (y);
+ if (p > INT_MAX-2-(ebuf-estr)-pl)
+ return -1;
if (p && s-buf-2 < p)
l = (p+2) + (ebuf-estr);
else
@@ -383,17 +385,22 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
p = MIN(p,MAX(0,9*(z-r-1)+e-j));
}
}
+ if (p > INT_MAX-1-(p || (fl&ALT_FORM)))
+ return -1;
l = 1 + p + (p || (fl&ALT_FORM));
if ((t|32)=='f') {
+ if (e > INT_MAX-l) return -1;
if (e>0) l+=e;
} else {
estr=fmt_u(e<0 ? -e : e, ebuf);
while(ebuf-estr<2) *--estr='0';
*--estr = (e<0 ? '-' : '+');
*--estr = t;
+ if (ebuf-estr > INT_MAX-l) return -1;
l += ebuf-estr;
}
+ if (l > INT_MAX-pl) return -1;
pad(f, ' ', w, pl+l, fl);
out(f, prefix, pl);
pad(f, '0', w, pl+l, fl^ZERO_PAD);
@@ -437,8 +444,10 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
static int getint(char **s) {
int i;
- for (i=0; isdigit(**s); (*s)++)
- i = 10*i + (**s-'0');
+ for (i=0; isdigit(**s); (*s)++) {
+ if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
+ else i = 10*i + (**s-'0');
+ }
return i;
}
@@ -446,12 +455,12 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
{
char *a, *z, *s=(char *)fmt;
unsigned l10n=0, fl;
- int w, p;
+ int w, p, xp;
union arg arg;
int argpos;
unsigned st, ps;
int cnt=0, l=0;
- int i;
+ size_t i;
char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
const char *prefix;
int t, pl;
@@ -459,18 +468,19 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
char mb[4];
for (;;) {
+ /* This error is only specified for snprintf, but since it's
+ * unspecified for other forms, do the same. Stop immediately
+ * on overflow; otherwise %n could produce wrong results. */
+ if (l > INT_MAX - cnt) goto overflow;
+
/* Update output count, end loop when fmt is exhausted */
- if (cnt >= 0) {
- if (l > INT_MAX - cnt) {
- errno = EOVERFLOW;
- cnt = -1;
- } else cnt += l;
- }
+ cnt += l;
if (!*s) break;
/* Handle literal text and %% format specifiers */
for (a=s; *s && *s!='%'; s++);
for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
+ if (z-a > INT_MAX-cnt) goto overflow;
l = z-a;
if (f) out(f, a, l);
if (l) continue;
@@ -498,9 +508,9 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
} else if (!l10n) {
w = f ? va_arg(*ap, int) : 0;
s++;
- } else return -1;
+ } else goto inval;
if (w<0) fl|=LEFT_ADJ, w=-w;
- } else if ((w=getint(&s))<0) return -1;
+ } else if ((w=getint(&s))<0) goto overflow;
/* Read precision */
if (*s=='.' && s[1]=='*') {
@@ -511,24 +521,29 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
} else if (!l10n) {
p = f ? va_arg(*ap, int) : 0;
s+=2;
- } else return -1;
+ } else goto inval;
+ xp = (p>=0);
} else if (*s=='.') {
s++;
p = getint(&s);
- } else p = -1;
+ xp = 1;
+ } else {
+ p = -1;
+ xp = 0;
+ }
/* Format specifier state machine */
st=0;
do {
- if (OOB(*s)) return -1;
+ if (OOB(*s)) goto inval;
ps=st;
st=states[st]S(*s++);
} while (st-1<STOP);
- if (!st) return -1;
+ if (!st) goto inval;
/* Check validity of argument type (nl/normal) */
if (st==NOARG) {
- if (argpos>=0) return -1;
+ if (argpos>=0) goto inval;
} else {
if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
else if (f) pop_arg(&arg, st, ap);
@@ -584,6 +599,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
case 'u':
a = fmt_u(arg.i, z);
}
+ if (xp && p<0) goto overflow;
if (p>=0) fl &= ~ZERO_PAD;
if (!arg.i && !p) {
a=z;
@@ -599,9 +615,9 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
if (1) a = strerror(errno); else
case 's':
a = arg.p ? arg.p : "(null)";
- z = memchr(a, 0, p);
- if (!z) z=a+p;
- else p=z-a;
+ z = a + strnlen(a, p<0 ? INT_MAX : p);
+ if (p<0 && *z) goto overflow;
+ p = z-a;
fl &= ~ZERO_PAD;
break;
case 'C':
@@ -611,8 +627,9 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
p = -1;
case 'S':
ws = arg.p;
- for (i=l=0; i<0U+p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=0U+p-i; i+=l);
+ for (i=l=0; i<p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=p-i; i+=l);
if (l<0) return -1;
+ if (i > INT_MAX) goto overflow;
p = i;
pad(f, ' ', w, p, fl);
ws = arg.p;
@@ -623,12 +640,16 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
continue;
case 'e': case 'f': case 'g': case 'a':
case 'E': case 'F': case 'G': case 'A':
+ if (xp && p<0) goto overflow;
l = fmt_fp(f, arg.f, w, p, fl, t);
+ if (l<0) goto overflow;
continue;
}
if (p < z-a) p = z-a;
+ if (p > INT_MAX-pl) goto overflow;
if (w < pl+p) w = pl+p;
+ if (w > INT_MAX-cnt) goto overflow;
pad(f, ' ', w, pl+p, fl);
out(f, prefix, pl);
@@ -646,8 +667,15 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
pop_arg(nl_arg+i, nl_type[i], ap);
for (; i<=NL_ARGMAX && !nl_type[i]; i++);
- if (i<=NL_ARGMAX) return -1;
+ if (i<=NL_ARGMAX) goto inval;
return 1;
+
+inval:
+ errno = EINVAL;
+ return -1;
+overflow:
+ errno = EOVERFLOW;
+ return -1;
}
int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
diff --git a/src/stdio/vfwprintf.c b/src/stdio/vfwprintf.c
index f9f1ecf..b8fff20 100644
--- a/src/stdio/vfwprintf.c
+++ b/src/stdio/vfwprintf.c
@@ -154,8 +154,10 @@ static void out(FILE *f, const wchar_t *s, size_t l)
static int getint(wchar_t **s) {
int i;
- for (i=0; iswdigit(**s); (*s)++)
- i = 10*i + (**s-'0');
+ for (i=0; iswdigit(**s); (*s)++) {
+ if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
+ else i = 10*i + (**s-'0');
+ }
return i;
}
@@ -168,8 +170,8 @@ static const char sizeprefix['y'-'a'] = {
static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
{
wchar_t *a, *z, *s=(wchar_t *)fmt;
- unsigned l10n=0, litpct, fl;
- int w, p;
+ unsigned l10n=0, fl;
+ int w, p, xp;
union arg arg;
int argpos;
unsigned st, ps;
@@ -181,20 +183,19 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
wchar_t wc;
for (;;) {
+ /* This error is only specified for snprintf, but since it's
+ * unspecified for other forms, do the same. Stop immediately
+ * on overflow; otherwise %n could produce wrong results. */
+ if (l > INT_MAX - cnt) goto overflow;
+
/* Update output count, end loop when fmt is exhausted */
- if (cnt >= 0) {
- if (l > INT_MAX - cnt) {
- if (!ferror(f)) errno = EOVERFLOW;
- cnt = -1;
- } else cnt += l;
- }
+ cnt += l;
if (!*s) break;
/* Handle literal text and %% format specifiers */
for (a=s; *s && *s!='%'; s++);
- litpct = wcsspn(s, L"%")/2; /* Optimize %%%% runs */
- z = s+litpct;
- s += 2*litpct;
+ for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
+ if (z-a > INT_MAX-cnt) goto overflow;
l = z-a;
if (f) out(f, a, l);
if (l) continue;
@@ -222,9 +223,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
} else if (!l10n) {
w = f ? va_arg(*ap, int) : 0;
s++;
- } else return -1;
+ } else goto inval;
if (w<0) fl|=LEFT_ADJ, w=-w;
- } else if ((w=getint(&s))<0) return -1;
+ } else if ((w=getint(&s))<0) goto overflow;
/* Read precision */
if (*s=='.' && s[1]=='*') {
@@ -235,24 +236,29 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
} else if (!l10n) {
p = f ? va_arg(*ap, int) : 0;
s+=2;
- } else return -1;
+ } else goto inval;
+ xp = (p>=0);
} else if (*s=='.') {
s++;
p = getint(&s);
- } else p = -1;
+ xp = 1;
+ } else {
+ p = -1;
+ xp = 0;
+ }
/* Format specifier state machine */
st=0;
do {
- if (OOB(*s)) return -1;
+ if (OOB(*s)) goto inval;
ps=st;
st=states[st]S(*s++);
} while (st-1<STOP);
- if (!st) return -1;
+ if (!st) goto inval;
/* Check validity of argument type (nl/normal) */
if (st==NOARG) {
- if (argpos>=0) return -1;
+ if (argpos>=0) goto inval;
} else {
if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
else if (f) pop_arg(&arg, st, ap);
@@ -285,8 +291,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
continue;
case 'S':
a = arg.p;
- z = wmemchr(a, 0, p);
- if (z) p=z-a;
+ z = a + wcsnlen(a, p<0 ? INT_MAX : p);
+ if (p<0 && *z) goto overflow;
+ p = z-a;
if (w<p) w=p;
if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
out(f, a, p);
@@ -298,9 +305,9 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
case 's':
if (!arg.p) arg.p = "(null)";
bs = arg.p;
- if (p<0) p = INT_MAX;
- for (i=l=0; l<p && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++);
+ for (i=l=0; l<(p<0?INT_MAX:p) && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++);
if (i<0) return -1;
+ if (p<0 && *bs) goto overflow;
p=l;
if (w<p) w=p;
if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
@@ -315,6 +322,7 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
continue;
}
+ if (xp && p<0) goto overflow;
snprintf(charfmt, sizeof charfmt, "%%%s%s%s%s%s*.*%c%c",
"#"+!(fl & ALT_FORM),
"+"+!(fl & MARK_POS),
@@ -341,6 +349,13 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
for (; i<=NL_ARGMAX && !nl_type[i]; i++);
if (i<=NL_ARGMAX) return -1;
return 1;
+
+inval:
+ errno = EINVAL;
+ return -1;
+overflow:
+ errno = EOVERFLOW;
+ return -1;
}
int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
--
cgit v0.11.2

View File

@ -0,0 +1,38 @@
From 688d3da0f1730daddbc954bbc2d27cc96ceee04c Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Tue, 4 Oct 2016 03:58:56 +0200
Subject: math: fix pow signed shift ub
j is int32_t and thus j<<31 is undefined if j==1, so j is changed to
uint32_t locally as a quick fix, the generated code is not affected.
(this is a strict conformance fix, future c standard may allow 1<<31,
see DR 463. the bug was inherited from freebsd fdlibm, the proper fix
is to use uint32_t for all bit hacks, but that requires more intrusive
changes.)
reported by Daniel Sabogal
---
src/math/pow.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/math/pow.c b/src/math/pow.c
index b66f632..3ddc1b6 100644
--- a/src/math/pow.c
+++ b/src/math/pow.c
@@ -125,11 +125,11 @@ double pow(double x, double y)
else if (iy >= 0x3ff00000) {
k = (iy>>20) - 0x3ff; /* exponent */
if (k > 20) {
- j = ly>>(52-k);
+ uint32_t j = ly>>(52-k);
if ((j<<(52-k)) == ly)
yisint = 2 - (j&1);
} else if (ly == 0) {
- j = iy>>(20-k);
+ uint32_t j = iy>>(20-k);
if ((j<<(20-k)) == iy)
yisint = 2 - (j&1);
}
--
cgit v0.11.2

View File

@ -0,0 +1,30 @@
From 3ca2d2d4aef910663785fe232d7d2127a22d8a84 Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogalcc@gmail.com>
Date: Sat, 17 Sep 2016 12:05:45 -0400
Subject: fix clock_nanosleep error case
posix requires that EINVAL be returned if the first parameter specifies
the cpu-time clock of the calling thread (CLOCK_THREAD_CPUTIME_ID).
linux returns ENOTSUP instead so we handle this.
---
src/time/clock_nanosleep.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/time/clock_nanosleep.c b/src/time/clock_nanosleep.c
index ec87b9e..9e4d9f1 100644
--- a/src/time/clock_nanosleep.c
+++ b/src/time/clock_nanosleep.c
@@ -1,8 +1,10 @@
#include <time.h>
+#include <errno.h>
#include "syscall.h"
#include "libc.h"
int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
{
- return -__syscall_cp(SYS_clock_nanosleep, clk, flags, req, rem);
+ int r = -__syscall_cp(SYS_clock_nanosleep, clk, flags, req, rem);
+ return clk == CLOCK_THREAD_CPUTIME_ID ? EINVAL : r;
}
--
cgit v0.11.2

View File

@ -0,0 +1,58 @@
From 8fb28b0b3e7a5e958fb844722a4b2ef9bc244af1 Mon Sep 17 00:00:00 2001
From: Felix Janda <felix.janda@posteo.de>
Date: Fri, 16 Sep 2016 20:54:00 -0400
Subject: add pthread_setname_np
the thread name is displayed by gdb's "info threads".
---
include/pthread.h | 1 +
src/thread/pthread_setname_np.c | 26 ++++++++++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 src/thread/pthread_setname_np.c
diff --git a/include/pthread.h b/include/pthread.h
index 3d2e0c4..94ef919 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -214,6 +214,7 @@ struct cpu_set_t;
int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
int pthread_getattr_np(pthread_t, pthread_attr_t *);
+int pthread_setname_np(pthread_t, const char *);
int pthread_tryjoin_np(pthread_t, void **);
int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
#endif
diff --git a/src/thread/pthread_setname_np.c b/src/thread/pthread_setname_np.c
new file mode 100644
index 0000000..82d35e1
--- /dev/null
+++ b/src/thread/pthread_setname_np.c
@@ -0,0 +1,26 @@
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/prctl.h>
+
+#include "pthread_impl.h"
+
+int pthread_setname_np(pthread_t thread, const char *name)
+{
+ int fd, cs, status = 0;
+ char f[sizeof "/proc/self/task//comm" + 3*sizeof(int)];
+ size_t len;
+
+ if ((len = strnlen(name, 16)) > 15) return ERANGE;
+
+ if (thread == pthread_self())
+ return prctl(PR_SET_NAME, (unsigned long)name, 0UL, 0UL, 0UL) ? errno : 0;
+
+ snprintf(f, sizeof f, "/proc/self/task/%d/comm", thread->tid);
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+ if ((fd = open(f, O_WRONLY)) < 0 || write(fd, name, len) < 0) status = errno;
+ if (fd >= 0) close(fd);
+ pthread_setcancelstate(cs, 0);
+ return status;
+}
--
cgit v0.11.2

View File

@ -0,0 +1,30 @@
From 51ab6db4ed115d079d7131975e4adb074ba9ef9d Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Wed, 12 Oct 2016 00:49:59 +0200
Subject: fix float formatting of some exact halfway cases
in nearest rounding mode exact halfway cases were not following the
round to even rule if the rounding happened at a base 1000000000 digit
boundary of the internal representation and the previous digit was odd.
e.g. printf("%.0f", 1.5) printed 1 instead of 2.
---
src/stdio/vfprintf.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index e2ab2dc..60da14d 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -345,7 +345,8 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
if (x || d+1!=z) {
long double round = 2/LDBL_EPSILON;
long double small;
- if (*d/i & 1) round += 2;
+ if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1)))
+ round += 2;
if (x<i/2) small=0x0.8p0;
else if (x==i/2 && d+1==z) small=0x1.0p0;
else small=0x1.8p0;
--
cgit v0.11.2

View File

@ -0,0 +1,24 @@
From b24f1d2520c87077cef21e085893e5f3c565a6df Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 20 Oct 2016 12:13:33 -0400
Subject: fix getopt_long_only misinterpreting "--" as an option
---
src/misc/getopt_long.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/misc/getopt_long.c b/src/misc/getopt_long.c
index 480c001..c6e1462 100644
--- a/src/misc/getopt_long.c
+++ b/src/misc/getopt_long.c
@@ -53,7 +53,7 @@ static int __getopt_long_core(int argc, char *const *argv, const char *optstring
{
optarg = 0;
if (longopts && argv[optind][0] == '-' &&
- ((longonly && argv[optind][1]) ||
+ ((longonly && argv[optind][1] && argv[optind][1] != '-') ||
(argv[optind][1] == '-' && argv[optind][2])))
{
int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
--
cgit v0.11.2

View File

@ -0,0 +1,33 @@
From f33b17585058381491e6fda08f491b8e48c7980c Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Thu, 20 Oct 2016 13:22:20 -0400
Subject: fix gratuitous undefined behavior in strptime
accessing an object of type const char *restrict as if it had type
char * is not defined.
---
src/time/strptime.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/time/strptime.c b/src/time/strptime.c
index f41f55f..55c7ed1 100644
--- a/src/time/strptime.c
+++ b/src/time/strptime.c
@@ -22,8 +22,13 @@ char *strptime(const char *restrict s, const char *restrict f, struct tm *restri
}
f++;
if (*f == '+') f++;
- if (isdigit(*f)) w=strtoul(f, (void *)&f, 10);
- else w=-1;
+ if (isdigit(*f)) {
+ char *new_f;
+ w=strtoul(f, &new_f, 10);
+ f = new_f;
+ } else {
+ w=-1;
+ }
adj=0;
switch (*f++) {
case 'a': case 'A':
--
cgit v0.11.2

View File

@ -0,0 +1,36 @@
From d184a09e0529f33d8ddddb8825039133483a2c41 Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Sun, 4 Sep 2016 04:46:00 +0200
Subject: fix strtod and strtof rounding with many trailing zeros
in certain cases excessive trailing zeros could cause incorrect
rounding from long double to double or float in decfloat.
e.g. in strtof("9444733528689243848704.000000", 0) the argument
is 0x1.000001p+73, exactly halfway between two representible floats,
this incorrectly got rounded to 0x1.000002p+73 instead of 0x1p+73,
but with less trailing 0 the rounding was fine.
the fix makes sure that the z index always points one past the last
non-zero digit in the base 10^9 representation, this way trailing
zeros don't affect the rounding logic.
---
src/internal/floatscan.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c
index eef70df..80305ee 100644
--- a/src/internal/floatscan.c
+++ b/src/internal/floatscan.c
@@ -172,6 +172,9 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po
return sign * (long double)x[0] * p10s[rp-10];
}
+ /* Drop trailing zeros */
+ for (; !x[z-1]; z--);
+
/* Align radix point to B1B digit boundary */
if (rp % 9) {
int rpm9 = rp>=0 ? rp%9 : rp%9+9;
--
cgit v0.11.2

View File

@ -0,0 +1,38 @@
From 6ffdc4579ffb34f4aab69ab4c081badabc7c0a9a Mon Sep 17 00:00:00 2001
From: Szabolcs Nagy <nsz@port70.net>
Date: Sun, 4 Sep 2016 04:51:03 +0200
Subject: fix strtod int optimization in non-nearest rounding mode
the mid-sized integer optimization relies on lnz set up properly
to mark the last non-zero decimal digit, but this was not done
if the non-zero digit lied outside the KMAX digits of the base
10^9 number representation.
so if the fractional part was a very long list of zeros (>2048*9 on
x86) followed by non-zero digits then the integer optimization could
kick in discarding the tiny non-zero fraction which can mean wrong
result on non-nearest rounding mode.
strtof, strtod and strtold were all affected.
---
src/internal/floatscan.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/internal/floatscan.c b/src/internal/floatscan.c
index 80305ee..ae09852 100644
--- a/src/internal/floatscan.c
+++ b/src/internal/floatscan.c
@@ -110,7 +110,10 @@ static long double decfloat(FILE *f, int c, int bits, int emin, int sign, int po
gotdig=1;
} else {
dc++;
- if (c!='0') x[KMAX-4] |= 1;
+ if (c!='0') {
+ lnz = (KMAX-4)*9;
+ x[KMAX-4] |= 1;
+ }
}
}
if (!gotrad) lrp=dc;
--
cgit v0.11.2

View File

@ -0,0 +1,39 @@
From bc1e7731cee963e422575f81048792f4d5db9641 Mon Sep 17 00:00:00 2001
From: Daniel Sabogal <dsabogal@ufl.edu>
Date: Wed, 2 Nov 2016 22:29:36 -0400
Subject: fix integer overflow of tm_year in __secs_to_tm
the overflow check for years+100 did not account for the extra
year computed from the remaining months. instead, perform this
check after obtaining the final number of years.
---
src/time/__secs_to_tm.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/time/__secs_to_tm.c b/src/time/__secs_to_tm.c
index 3a3123a..093d902 100644
--- a/src/time/__secs_to_tm.c
+++ b/src/time/__secs_to_tm.c
@@ -60,15 +60,16 @@ int __secs_to_tm(long long t, struct tm *tm)
for (months=0; days_in_month[months] <= remdays; months++)
remdays -= days_in_month[months];
+ if (months >= 10) {
+ months -= 12;
+ years++;
+ }
+
if (years+100 > INT_MAX || years+100 < INT_MIN)
return -1;
tm->tm_year = years + 100;
tm->tm_mon = months + 2;
- if (tm->tm_mon >= 12) {
- tm->tm_mon -=12;
- tm->tm_year++;
- }
tm->tm_mday = remdays + 1;
tm->tm_wday = wday;
tm->tm_yday = yday;
--
cgit v0.11.2

View File

@ -0,0 +1,36 @@
From 7442442ccc665641a8827177e8e7ed45bbbd6584 Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Mon, 7 Nov 2016 20:39:59 -0500
Subject: fix swprintf internal buffer state and error handling
the swprintf write callback never reset its buffer pointers, so after
its 256-byte buffer filled up, it would keep repeating those bytes
over and over in the output until the destination buffer filled up. it
also failed to set the error indicator for the stream on EILSEQ,
potentially allowing output to continue after the error.
---
src/stdio/vswprintf.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/stdio/vswprintf.c b/src/stdio/vswprintf.c
index 7d237ba..6eb2f6a 100644
--- a/src/stdio/vswprintf.c
+++ b/src/stdio/vswprintf.c
@@ -24,7 +24,14 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l)
c->ws++;
}
*c->ws = 0;
- return i<0 ? i : l0;
+ if (i < 0) {
+ f->wpos = f->wbase = f->wend = 0;
+ f->flags |= F_ERR;
+ return i;
+ }
+ f->wend = f->buf + f->buf_size;
+ f->wpos = f->wbase = f->buf;
+ return l0;
}
int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_list ap)
--
cgit v0.11.2

View File

@ -0,0 +1,32 @@
From 4078a5c31fa67987051c2180db7a07702534032f Mon Sep 17 00:00:00 2001
From: Rich Felker <dalias@aerifal.cx>
Date: Tue, 8 Nov 2016 18:03:42 -0500
Subject: fix build regression on archs with variable page size
commit 31fb174dd295e50f7c5cf18d31fcfd5fe5a063b7 used
DEFAULT_GUARD_SIZE from pthread_impl.h in a static initializer,
breaking build on archs where its definition, PAGE_SIZE, is not a
constant. instead, just define DEFAULT_GUARD_SIZE as 4096, the minimal
page size on any arch we support. pthread_create rounds up to whole
pages anyway, so defining it to 1 would also work, but a moderately
meaningful value is nicer to programs that use
pthread_attr_getguardsize on default-initialized attribute objects.
---
src/internal/pthread_impl.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index 3890bb5..7a679db 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -143,7 +143,7 @@ void __block_app_sigs(void *);
void __restore_sigs(void *);
#define DEFAULT_STACK_SIZE 81920
-#define DEFAULT_GUARD_SIZE PAGE_SIZE
+#define DEFAULT_GUARD_SIZE 4096
#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1)
--
cgit v0.11.2