These commits are cherry-picked from the "release/2.27/master" branch. https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.27/master Currently, we have the following (with NEWS and ChangeLog entries omitted). 56170e064e2b21ce204f0817733e92f1730541ea 516fa6080481a1433c173320b1c1432868e1e38a f36553bf6a4f69070f99badbdab5802b43e6e211 7c6304182b9f422b782ace1cdd3efbde056aec36 78a90c2f74a2012dd3eff302189e47ff6779a757 1e52d8e65a58c49a48549053a1b89c06240e0c6c 55ad82e45c313454de657931898e974a7a036cad From 56170e064e2b21ce204f0817733e92f1730541ea Mon Sep 17 00:00:00 2001 From: Igor Gnatenko Date: Wed, 7 Feb 2018 13:53:10 +0100 Subject: [PATCH] Linux: use reserved name __key in pkey_get [BZ #22797] _key is not reserved name and we should avoid using that. It seems that it was simple typo when pkey_* was implemented. (cherry picked from commit 388ff7bd0d57d7061fdd39a2f26f65687e8058da) diff --git a/sysdeps/unix/sysv/linux/bits/mman-shared.h b/sysdeps/unix/sysv/linux/bits/mman-shared.h index 7715e680ca..d15ba95c9d 100644 --- a/sysdeps/unix/sysv/linux/bits/mman-shared.h +++ b/sysdeps/unix/sysv/linux/bits/mman-shared.h @@ -61,7 +61,7 @@ int pkey_set (int __key, unsigned int __access_rights) __THROW; /* Return the access rights for the current thread for KEY, which must have been allocated using pkey_alloc. */ -int pkey_get (int _key) __THROW; +int pkey_get (int __key) __THROW; /* Free an allocated protection key, which must have been allocated using pkey_alloc. */ From 516fa6080481a1433c173320b1c1432868e1e38a Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Fri, 29 Dec 2017 23:19:32 +0000 Subject: [PATCH] linux/aarch64: sync sys/ptrace.h with Linux 4.15 [BZ #22433] Remove compat-specific constants that were never exported by kernel headers under these names. Before linux commit v3.7-rc1~16^2~1 they were exported with COMPAT_ prefix, and since that commit they are not exported at all. * sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h (__ptrace_request): Remove arm-specific PTRACE_GET_THREAD_AREA, PTRACE_GETHBPREGS, and PTRACE_SETHBPREGS. (cherry picked from commit 2fd4bbaa1446f1be700e10c526cf585a796c4991) diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h index 4be45b95ff..444edbb702 100644 --- a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h +++ b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h @@ -78,18 +78,10 @@ enum __ptrace_request PTRACE_DETACH = 17, #define PT_DETACH PTRACE_DETACH - PTRACE_GET_THREAD_AREA = 22, - /* Continue and stop at the next entry to or return from syscall. */ PTRACE_SYSCALL = 24, #define PT_SYSCALL PTRACE_SYSCALL - /* Get all hardware breakpoint registers. */ - PTRACE_GETHBPREGS = 29, - - /* Set all hardware breakpoint registers. */ - PTRACE_SETHBPREGS = 30, - /* Set ptrace filter options. */ PTRACE_SETOPTIONS = 0x4200, #define PT_SETOPTIONS PTRACE_SETOPTIONS From f36553bf6a4f69070f99badbdab5802b43e6e211 Mon Sep 17 00:00:00 2001 From: Mike FABIAN Date: Mon, 19 Feb 2018 21:59:30 +0100 Subject: [PATCH] =?UTF-8?q?Add=20missing=20=E2=80=9Creorder-end=E2=80=9D?= =?UTF-8?q?=20in=20LC=5FCOLLATE=20of=20et=5FEE=20[BZ=20#22517]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [BZ #22517] * localedata/locales/et_EE (LC_COLLATE): add missing “reorder-end” (cherry picked from commit 7ec5f9465e732e668d0dc94ac078ba68056d6d0a) diff --git a/localedata/locales/et_EE b/localedata/locales/et_EE index 9cb55b568f..bab7493c98 100644 --- a/localedata/locales/et_EE +++ b/localedata/locales/et_EE @@ -103,6 +103,8 @@ reorder-after ;;;IGNORE % ü ;;;IGNORE % Ü +reorder-end + END LC_COLLATE LC_CTYPE From 7c6304182b9f422b782ace1cdd3efbde056aec36 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Thu, 1 Mar 2018 23:20:45 -0500 Subject: [PATCH] [BZ #22342] Fix netgroup cache keys. Unlike other nscd caches, the netgroup cache contains two types of records - those for "iterate through a netgroup" (i.e. setnetgrent()) and those for "is this user in this netgroup" (i.e. innetgr()), i.e. full and partial records. The timeout code assumes these records have the same key for the group name, so that the collection of records that is "this netgroup" can be expired as a unit. However, the keys are not the same, as the in-netgroup key is generated by nscd rather than being passed to it from elsewhere, and is generated without the trailing NUL. All other keys have the trailing NUL, and as noted in the linked BZ, debug statements confirm that two keys for the same netgroup are added to the cache with two different lengths. The result of this is that as records in the cache expire, the purge code only cleans out one of the two types of entries, resulting in stale, possibly incorrect, and possibly inconsistent cache data. The patch simply includes the existing NUL in the computation for the key length ('key' points to the char after the NUL, and 'group' to the first char of the group, so 'key-group' includes the first char to the NUL, inclusive). [BZ #22342] * nscd/netgroupcache.c (addinnetgrX): Include trailing NUL in key value. Reviewed-by: Carlos O'Donell (cherry picked from commit 1c81d55fc4b07b51adf68558ba74ce975153e580) diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c index b832c9315f..2f187b208c 100644 --- a/nscd/netgroupcache.c +++ b/nscd/netgroupcache.c @@ -480,7 +480,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req, { const char *group = key; key = (char *) rawmemchr (key, '\0') + 1; - size_t group_len = key - group - 1; + size_t group_len = key - group; const char *host = *key++ ? key : NULL; if (host != NULL) key = (char *) rawmemchr (key, '\0') + 1; From 78a90c2f74a2012dd3eff302189e47ff6779a757 Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Fri, 2 Mar 2018 23:07:14 +0100 Subject: [PATCH] Fix multiple definitions of __nss_*_database (bug 22918) (cherry picked from commit eaf6753f8aac33a36deb98c1031d1bad7b593d2d) diff --git a/nscd/gai.c b/nscd/gai.c index d081747797..576fd0045b 100644 --- a/nscd/gai.c +++ b/nscd/gai.c @@ -45,3 +45,6 @@ #ifdef HAVE_LIBIDN # include #endif + +/* Some variables normally defined in libc. */ +service_user *__nss_hosts_database attribute_hidden; diff --git a/nss/nsswitch.c b/nss/nsswitch.c index d5e655974f..b0f0c11a3e 100644 --- a/nss/nsswitch.c +++ b/nss/nsswitch.c @@ -62,7 +62,7 @@ static service_library *nss_new_service (name_database *database, /* Declare external database variables. */ #define DEFINE_DATABASE(name) \ - extern service_user *__nss_##name##_database attribute_hidden; \ + service_user *__nss_##name##_database attribute_hidden; \ weak_extern (__nss_##name##_database) #include "databases.def" #undef DEFINE_DATABASE diff --git a/nss/nsswitch.h b/nss/nsswitch.h index eccb535ef5..63573b9ebc 100644 --- a/nss/nsswitch.h +++ b/nss/nsswitch.h @@ -226,10 +226,10 @@ libc_hidden_proto (__nss_hostname_digits_dots) #define MAX_NR_ADDRS 48 /* Prototypes for __nss_*_lookup2 functions. */ -#define DEFINE_DATABASE(arg) \ - service_user *__nss_##arg##_database attribute_hidden; \ - int __nss_##arg##_lookup2 (service_user **, const char *, \ - const char *, void **); \ +#define DEFINE_DATABASE(arg) \ + extern service_user *__nss_##arg##_database attribute_hidden; \ + int __nss_##arg##_lookup2 (service_user **, const char *, \ + const char *, void **); \ libc_hidden_proto (__nss_##arg##_lookup2) #include "databases.def" #undef DEFINE_DATABASE diff --git a/posix/tst-rfc3484-2.c b/posix/tst-rfc3484-2.c index f509534ca9..8c64ac59ff 100644 --- a/posix/tst-rfc3484-2.c +++ b/posix/tst-rfc3484-2.c @@ -58,6 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" +service_user *__nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ diff --git a/posix/tst-rfc3484-3.c b/posix/tst-rfc3484-3.c index ae44087a10..1c61aaf844 100644 --- a/posix/tst-rfc3484-3.c +++ b/posix/tst-rfc3484-3.c @@ -58,6 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" +service_user *__nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ diff --git a/posix/tst-rfc3484.c b/posix/tst-rfc3484.c index 7f191abbbc..8f45848e44 100644 --- a/posix/tst-rfc3484.c +++ b/posix/tst-rfc3484.c @@ -58,6 +58,7 @@ _res_hconf_init (void) #undef USE_NSCD #include "../sysdeps/posix/getaddrinfo.c" +service_user *__nss_hosts_database attribute_hidden; /* This is the beginning of the real test code. The above defines (among other things) the function rfc3484_sort. */ From 1e52d8e65a58c49a48549053a1b89c06240e0c6c Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Fri, 17 Nov 2017 16:04:29 -0200 Subject: [PATCH] i386: Fix i386 sigaction sa_restorer initialization (BZ#21269) This patch fixes the i386 sa_restorer field initialization for sigaction syscall for kernel with vDSO. As described in bug report, i386 Linux (and compat on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a request for stack switching if the SS segment is 'funny'. This means that anything that tries to mix glibc's signal handling with segmentation (for instance through modify_ldt syscall) is randomly broken depending on what values lands in sa_restorer. The testcase added is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, more specifically in do_multicpu_tests function. The main changes are: - C11 atomics instead of plain access. - Remove x86_64 support which simplifies the syscall handling and fallbacks. - Replicate only the test required to trigger the issue. Checked on i686-linux-gnu. [BZ #21269] * sysdeps/unix/sysv/linux/i386/Makefile (tests): Add tst-bz21269. * sysdeps/unix/sysv/linux/i386/sigaction.c (SET_SA_RESTORER): Clear sa_restorer for vDSO case. * sysdeps/unix/sysv/linux/i386/tst-bz21269.c: New file. (cherry picked from commit 68448be208ee06e76665918b37b0a57e3e00c8b4) diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile index 4080b8c966..da716e2c1b 100644 --- a/sysdeps/unix/sysv/linux/i386/Makefile +++ b/sysdeps/unix/sysv/linux/i386/Makefile @@ -3,6 +3,9 @@ default-abi := 32 ifeq ($(subdir),misc) sysdep_routines += ioperm iopl vm86 + +tests += tst-bz21269 +$(objpfx)tst-bz21269: $(shared-thread-library) endif ifeq ($(subdir),elf) diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c index a5eb9e0d3e..177ff60ee6 100644 --- a/sysdeps/unix/sysv/linux/i386/sigaction.c +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c @@ -42,7 +42,6 @@ extern void restore_rt (void) asm ("__restore_rt") attribute_hidden; #endif extern void restore (void) asm ("__restore") attribute_hidden; - /* If ACT is not NULL, change the action for SIG to *ACT. If OACT is not NULL, put the old action for SIG in *OACT. */ int @@ -65,6 +64,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore); } + else + kact.sa_restorer = NULL; } /* XXX The size argument hopefully will have to be changed to the diff --git a/sysdeps/unix/sysv/linux/i386/tst-bz21269.c b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c new file mode 100644 index 0000000000..353e36507d --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/tst-bz21269.c @@ -0,0 +1,233 @@ +/* Test for i386 sigaction sa_restorer handling (BZ#21269) + Copyright (C) 2017 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 + . */ + +/* This is based on Linux test tools/testing/selftests/x86/ldt_gdt.c, + more specifically in do_multicpu_tests function. The main changes + are: + + - C11 atomics instead of plain access. + - Remove x86_64 support which simplifies the syscall handling + and fallbacks. + - Replicate only the test required to trigger the issue for the + BZ#21269. */ + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static int +xset_thread_area (struct user_desc *u_info) +{ + long ret = syscall (SYS_set_thread_area, u_info); + TEST_VERIFY_EXIT (ret == 0); + return ret; +} + +static void +xmodify_ldt (int func, const void *ptr, unsigned long bytecount) +{ + TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0); +} + +static int +futex (int *uaddr, int futex_op, int val, void *timeout, int *uaddr2, + int val3) +{ + return syscall (SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3); +} + +static void +xsethandler (int sig, void (*handler)(int, siginfo_t *, void *), int flags) +{ + struct sigaction sa = { 0 }; + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + TEST_VERIFY_EXIT (sigemptyset (&sa.sa_mask) == 0); + TEST_VERIFY_EXIT (sigaction (sig, &sa, 0) == 0); +} + +static jmp_buf jmpbuf; + +static void +sigsegv_handler (int sig, siginfo_t *info, void *ctx_void) +{ + siglongjmp (jmpbuf, 1); +} + +/* Points to an array of 1024 ints, each holding its own index. */ +static const unsigned int *counter_page; +static struct user_desc *low_user_desc; +static struct user_desc *low_user_desc_clear; /* Used to delete GDT entry. */ +static int gdt_entry_num; + +static void +setup_counter_page (void) +{ + long page_size = sysconf (_SC_PAGE_SIZE); + TEST_VERIFY_EXIT (page_size > 0); + unsigned int *page = xmmap (NULL, page_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); + for (int i = 0; i < (page_size / sizeof (unsigned int)); i++) + page[i] = i; + counter_page = page; +} + +static void +setup_low_user_desc (void) +{ + low_user_desc = xmmap (NULL, 2 * sizeof (struct user_desc), + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, -1); + + low_user_desc->entry_number = -1; + low_user_desc->base_addr = (unsigned long) &counter_page[1]; + low_user_desc->limit = 0xffff; + low_user_desc->seg_32bit = 1; + low_user_desc->contents = 0; + low_user_desc->read_exec_only = 0; + low_user_desc->limit_in_pages = 1; + low_user_desc->seg_not_present = 0; + low_user_desc->useable = 0; + + xset_thread_area (low_user_desc); + + low_user_desc_clear = low_user_desc + 1; + low_user_desc_clear->entry_number = gdt_entry_num; + low_user_desc_clear->read_exec_only = 1; + low_user_desc_clear->seg_not_present = 1; +} + +/* Possible values of futex: + 0: thread is idle. + 1: thread armed. + 2: thread should clear LDT entry 0. + 3: thread should exit. */ +static atomic_uint ftx; + +static void * +threadproc (void *ctx) +{ + while (1) + { + futex ((int *) &ftx, FUTEX_WAIT, 1, NULL, NULL, 0); + while (atomic_load (&ftx) != 2) + { + if (atomic_load (&ftx) >= 3) + return NULL; + } + + /* clear LDT entry 0. */ + const struct user_desc desc = { 0 }; + xmodify_ldt (1, &desc, sizeof (desc)); + + /* If ftx == 2, set it to zero, If ftx == 100, quit. */ + if (atomic_fetch_add (&ftx, -2) != 2) + return NULL; + } +} + + +/* As described in testcase, for historical reasons x86_32 Linux (and compat + on x86_64) interprets SA_RESTORER clear with nonzero sa_restorer as a + request for stack switching if the SS segment is 'funny' (this is default + scenario for vDSO system). This means that anything that tries to mix + signal handling with segmentation should explicit clear the sa_restorer. + + This testcase check if sigaction in fact does it by changing the local + descriptor table (LDT) through the modify_ldt syscall and triggering + a synchronous segfault on iret fault by trying to install an invalid + segment. With a correct zeroed sa_restorer it should not trigger an + 'real' SEGSEGV and allows the siglongjmp in signal handler. */ + +static int +do_test (void) +{ + setup_counter_page (); + setup_low_user_desc (); + + pthread_t thread; + unsigned short orig_ss; + + xsethandler (SIGSEGV, sigsegv_handler, 0); + /* 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */ + xsethandler (SIGILL, sigsegv_handler, 0); + + thread = xpthread_create (0, threadproc, 0); + + asm volatile ("mov %%ss, %0" : "=rm" (orig_ss)); + + for (int i = 0; i < 5; i++) + { + if (sigsetjmp (jmpbuf, 1) != 0) + continue; + + /* Make sure the thread is ready after the last test. */ + while (atomic_load (&ftx) != 0) + ; + + struct user_desc desc = { + .entry_number = 0, + .base_addr = 0, + .limit = 0xffff, + .seg_32bit = 1, + .contents = 0, + .read_exec_only = 0, + .limit_in_pages = 1, + .seg_not_present = 0, + .useable = 0 + }; + + xmodify_ldt (0x11, &desc, sizeof (desc)); + + /* Arm the thread. */ + ftx = 1; + futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + asm volatile ("mov %0, %%ss" : : "r" (0x7)); + + /* Fire up thread modify_ldt call. */ + atomic_store (&ftx, 2); + + while (atomic_load (&ftx) != 0) + ; + + /* On success, modify_ldt will segfault us synchronously and we will + escape via siglongjmp. */ + support_record_failure (); + } + + atomic_store (&ftx, 100); + futex ((int*) &ftx, FUTEX_WAKE, 0, NULL, NULL, 0); + + xpthread_join (thread); + + return 0; +} + +#include From 55ad82e45c313454de657931898e974a7a036cad Mon Sep 17 00:00:00 2001 From: Andrew Senkevich Date: Fri, 23 Mar 2018 16:19:45 +0100 Subject: [PATCH] Fix i386 memmove issue (bug 22644). [BZ #22644] * sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S: Fixed branch conditions. * string/test-memmove.c (do_test2): New testcase. (cherry picked from commit cd66c0e584c6d692bc8347b5e72723d02b8a8ada) diff --git a/string/test-memmove.c b/string/test-memmove.c index edc7a4c3bf..64e3651ba4 100644 --- a/string/test-memmove.c +++ b/string/test-memmove.c @@ -24,6 +24,7 @@ # define TEST_NAME "memmove" #endif #include "test-string.h" +#include char *simple_memmove (char *, const char *, size_t); @@ -245,6 +246,60 @@ do_random_tests (void) } } +static void +do_test2 (void) +{ + size_t size = 0x20000000; + uint32_t * large_buf; + + large_buf = mmap ((void*) 0x70000000, size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + + if (large_buf == MAP_FAILED) + error (EXIT_UNSUPPORTED, errno, "Large mmap failed"); + + if ((uintptr_t) large_buf > 0x80000000 - 128 + || 0x80000000 - (uintptr_t) large_buf > 0x20000000) + { + error (0, 0, "Large mmap allocated improperly"); + ret = EXIT_UNSUPPORTED; + munmap ((void *) large_buf, size); + return; + } + + size_t bytes_move = 0x80000000 - (uintptr_t) large_buf; + size_t arr_size = bytes_move / sizeof (uint32_t); + size_t i; + + FOR_EACH_IMPL (impl, 0) + { + for (i = 0; i < arr_size; i++) + large_buf[i] = (uint32_t) i; + + uint32_t * dst = &large_buf[33]; + +#ifdef TEST_BCOPY + CALL (impl, (char *) large_buf, (char *) dst, bytes_move); +#else + CALL (impl, (char *) dst, (char *) large_buf, bytes_move); +#endif + + for (i = 0; i < arr_size; i++) + { + if (dst[i] != (uint32_t) i) + { + error (0, 0, + "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"", + impl->name, dst, large_buf, i); + ret = 1; + break; + } + } + } + + munmap ((void *) large_buf, size); +} + int test_main (void) { @@ -284,6 +339,9 @@ test_main (void) } do_random_tests (); + + do_test2 (); + return ret; } diff --git a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S index 9c3bbe7e17..9aa17de99c 100644 --- a/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S +++ b/sysdeps/i386/i686/multiarch/memcpy-sse2-unaligned.S @@ -72,7 +72,7 @@ ENTRY (MEMCPY) cmp %edx, %eax # ifdef USE_AS_MEMMOVE - jg L(check_forward) + ja L(check_forward) L(mm_len_0_or_more_backward): /* Now do checks for lengths. We do [0..16], [16..32], [32..64], [64..128] @@ -81,7 +81,7 @@ L(mm_len_0_or_more_backward): jbe L(mm_len_0_16_bytes_backward) cmpl $32, %ecx - jg L(mm_len_32_or_more_backward) + ja L(mm_len_32_or_more_backward) /* Copy [0..32] and return. */ movdqu (%eax), %xmm0 @@ -92,7 +92,7 @@ L(mm_len_0_or_more_backward): L(mm_len_32_or_more_backward): cmpl $64, %ecx - jg L(mm_len_64_or_more_backward) + ja L(mm_len_64_or_more_backward) /* Copy [0..64] and return. */ movdqu (%eax), %xmm0 @@ -107,7 +107,7 @@ L(mm_len_32_or_more_backward): L(mm_len_64_or_more_backward): cmpl $128, %ecx - jg L(mm_len_128_or_more_backward) + ja L(mm_len_128_or_more_backward) /* Copy [0..128] and return. */ movdqu (%eax), %xmm0 @@ -132,7 +132,7 @@ L(mm_len_128_or_more_backward): add %ecx, %eax cmp %edx, %eax movl SRC(%esp), %eax - jle L(forward) + jbe L(forward) PUSH (%esi) PUSH (%edi) PUSH (%ebx) @@ -269,7 +269,7 @@ L(check_forward): add %edx, %ecx cmp %eax, %ecx movl LEN(%esp), %ecx - jle L(forward) + jbe L(forward) /* Now do checks for lengths. We do [0..16], [0..32], [0..64], [0..128] separately. */