forked from rpms/glibc
import CS git glibc-2.28-251.el8_10.37
This commit is contained in:
parent
2662609aa5
commit
01d571523d
77
SOURCES/glibc-RHEL-162891-1.patch
Normal file
77
SOURCES/glibc-RHEL-162891-1.patch
Normal file
@ -0,0 +1,77 @@
|
||||
commit 7ac6fad987c28dc5e0e7964084260f163179be68
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed May 15 07:16:47 2019 +0200
|
||||
|
||||
iconv: Remove public declaration of __gconv_transliterate
|
||||
|
||||
Commit ba7b4d294b01870ce3497971e9d07ee261cdc540 ("Complete the
|
||||
removal of __gconv_translit_find") added a declaration of the
|
||||
GLIBC_PRIVATE function, __gconv_transliterate, to the installed
|
||||
header <gconv.h>. It should have been added to the internal
|
||||
<gconv_int.h> header.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
diff --git a/iconv/gconv.h b/iconv/gconv.h
|
||||
index e53f4dba0e3530fc..9dcc509c12c4a343 100644
|
||||
--- a/iconv/gconv.h
|
||||
+++ b/iconv/gconv.h
|
||||
@@ -142,13 +142,4 @@ typedef struct __gconv_info
|
||||
__extension__ struct __gconv_step_data __data[0];
|
||||
} *__gconv_t;
|
||||
|
||||
-/* Transliteration using the locale's data. */
|
||||
-extern int __gconv_transliterate (struct __gconv_step *step,
|
||||
- struct __gconv_step_data *step_data,
|
||||
- const unsigned char *inbufstart,
|
||||
- const unsigned char **inbufp,
|
||||
- const unsigned char *inbufend,
|
||||
- unsigned char **outbufstart,
|
||||
- size_t *irreversible);
|
||||
-
|
||||
#endif /* gconv.h */
|
||||
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
|
||||
index 8067a341b0903e1b..6f908f283720520a 100644
|
||||
--- a/iconv/gconv_int.h
|
||||
+++ b/iconv/gconv_int.h
|
||||
@@ -276,6 +276,14 @@ extern void __gconv_get_builtin_trans (const char *name,
|
||||
struct __gconv_step *step)
|
||||
attribute_hidden;
|
||||
|
||||
+/* Transliteration using the locale's data. */
|
||||
+extern int __gconv_transliterate (struct __gconv_step *step,
|
||||
+ struct __gconv_step_data *step_data,
|
||||
+ const unsigned char *inbufstart,
|
||||
+ const unsigned char **inbufp,
|
||||
+ const unsigned char *inbufend,
|
||||
+ unsigned char **outbufstart,
|
||||
+ size_t *irreversible);
|
||||
libc_hidden_proto (__gconv_transliterate)
|
||||
|
||||
/* If NAME is an codeset alias expand it. */
|
||||
diff --git a/iconv/loop.c b/iconv/loop.c
|
||||
index d571b593c7b8da93..4adbe04ae3698411 100644
|
||||
--- a/iconv/loop.c
|
||||
+++ b/iconv/loop.c
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <endian.h>
|
||||
-#include <gconv.h>
|
||||
+#include <iconv/gconv_int.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
|
||||
index fa799305236001c7..9eb0200cc50a0afc 100644
|
||||
--- a/iconv/skeleton.c
|
||||
+++ b/iconv/skeleton.c
|
||||
@@ -133,7 +133,7 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
-#include <gconv.h>
|
||||
+#include <iconv/gconv_int.h>
|
||||
#include <string.h>
|
||||
#define __need_size_t
|
||||
#define __need_NULL
|
||||
369
SOURCES/glibc-RHEL-162891-2.patch
Normal file
369
SOURCES/glibc-RHEL-162891-2.patch
Normal file
@ -0,0 +1,369 @@
|
||||
commit 5729e0e9af590807df66a3db688008f9547bce9f
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Feb 10 14:09:10 2023 -0300
|
||||
|
||||
iconv: Remove _STRING_ARCH_unaligned usage for get/set macros
|
||||
|
||||
And use a packed structure instead. The compiler generates optimized
|
||||
unaligned code if the architecture supports it.
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
|
||||
|
||||
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
|
||||
index 6f908f283720520a..ebaf3518a95219f0 100644
|
||||
--- a/iconv/gconv_int.h
|
||||
+++ b/iconv/gconv_int.h
|
||||
@@ -27,6 +27,34 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
+/* We have to provide support for machines which are not able to handled
|
||||
+ unaligned memory accesses. Some of the character encodings have
|
||||
+ representations with a fixed width of 2 or 4 bytes. */
|
||||
+#define get16(addr) \
|
||||
+({ \
|
||||
+ const struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||
+ = (__typeof(__ptr))(addr); \
|
||||
+ __ptr->r; \
|
||||
+})
|
||||
+#define get32(addr) \
|
||||
+({ \
|
||||
+ const struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||
+ = (__typeof(__ptr))(addr); \
|
||||
+ __ptr->r; \
|
||||
+})
|
||||
+
|
||||
+#define put16(addr, val) \
|
||||
+do { \
|
||||
+ struct { uint16_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||
+ = (__typeof(__ptr))(addr); \
|
||||
+ __ptr->r = val; \
|
||||
+} while (0)
|
||||
+#define put32(addr, val) \
|
||||
+do { \
|
||||
+ struct { uint32_t r; } __attribute__ ((__packed__)) *__ptr \
|
||||
+ = (__typeof(__ptr))(addr); \
|
||||
+ __ptr->r = val; \
|
||||
+} while (0)
|
||||
|
||||
/* Type to represent search path. */
|
||||
struct path_elem
|
||||
diff --git a/iconv/loop.c b/iconv/loop.c
|
||||
index 4adbe04ae3698411..a9aa201eadc07bd9 100644
|
||||
--- a/iconv/loop.c
|
||||
+++ b/iconv/loop.c
|
||||
@@ -58,75 +58,10 @@
|
||||
#include <stddef.h>
|
||||
#include <libc-diag.h>
|
||||
|
||||
-/* We have to provide support for machines which are not able to handled
|
||||
- unaligned memory accesses. Some of the character encodings have
|
||||
- representations with a fixed width of 2 or 4 bytes. But if we cannot
|
||||
- access unaligned memory we still have to read byte-wise. */
|
||||
#undef FCTNAME2
|
||||
#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
||||
-/* We can handle unaligned memory access. */
|
||||
-# define get16(addr) *((const uint16_t *) (addr))
|
||||
-# define get32(addr) *((const uint32_t *) (addr))
|
||||
-
|
||||
-/* We need no special support for writing values either. */
|
||||
-# define put16(addr, val) *((uint16_t *) (addr)) = (val)
|
||||
-# define put32(addr, val) *((uint32_t *) (addr)) = (val)
|
||||
-
|
||||
# define FCTNAME2(name) name
|
||||
#else
|
||||
-/* Distinguish between big endian and little endian. */
|
||||
-# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
-# define get16(addr) \
|
||||
- (((const unsigned char *) (addr))[1] << 8 \
|
||||
- | ((const unsigned char *) (addr))[0])
|
||||
-# define get32(addr) \
|
||||
- (((((const unsigned char *) (addr))[3] << 8 \
|
||||
- | ((const unsigned char *) (addr))[2]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[1]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[0])
|
||||
-
|
||||
-# define put16(addr, val) \
|
||||
- ({ uint16_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- ((unsigned char *) (addr))[1] = __val >> 8; \
|
||||
- (void) 0; })
|
||||
-# define put32(addr, val) \
|
||||
- ({ uint32_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[2] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[3] = __val; \
|
||||
- (void) 0; })
|
||||
-# else
|
||||
-# define get16(addr) \
|
||||
- (((const unsigned char *) (addr))[0] << 8 \
|
||||
- | ((const unsigned char *) (addr))[1])
|
||||
-# define get32(addr) \
|
||||
- (((((const unsigned char *) (addr))[0] << 8 \
|
||||
- | ((const unsigned char *) (addr))[1]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[2]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[3])
|
||||
-
|
||||
-# define put16(addr, val) \
|
||||
- ({ uint16_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- ((unsigned char *) (addr))[0] = __val >> 8; \
|
||||
- (void) 0; })
|
||||
-# define put32(addr, val) \
|
||||
- ({ uint32_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[3] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[2] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- (void) 0; })
|
||||
-# endif
|
||||
-
|
||||
# define FCTNAME2(name) name##_unaligned
|
||||
#endif
|
||||
#define FCTNAME(name) FCTNAME2(name)
|
||||
@@ -350,10 +285,6 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
|
||||
#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
|
||||
&& MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
|
||||
&& MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
|
||||
-# undef get16
|
||||
-# undef get32
|
||||
-# undef put16
|
||||
-# undef put32
|
||||
# undef unaligned
|
||||
|
||||
# define DEFINE_UNALIGNED
|
||||
@@ -527,8 +458,4 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
|
||||
#undef LOOP_NEED_STATE
|
||||
#undef LOOP_NEED_FLAGS
|
||||
#undef LOOP_NEED_DATA
|
||||
-#undef get16
|
||||
-#undef get32
|
||||
-#undef put16
|
||||
-#undef put32
|
||||
#undef unaligned
|
||||
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
|
||||
index 9eb0200cc50a0afc..4f20a009d7ffb1db 100644
|
||||
--- a/iconv/skeleton.c
|
||||
+++ b/iconv/skeleton.c
|
||||
@@ -200,73 +200,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
-/* Define macros which can access unaligned buffers. These macros are
|
||||
- supposed to be used only in code outside the inner loops. For the inner
|
||||
- loops we have other definitions which allow optimized access. */
|
||||
-#if _STRING_ARCH_unaligned
|
||||
-/* We can handle unaligned memory access. */
|
||||
-# define get16u(addr) *((const uint16_t *) (addr))
|
||||
-# define get32u(addr) *((const uint32_t *) (addr))
|
||||
-
|
||||
-/* We need no special support for writing values either. */
|
||||
-# define put16u(addr, val) *((uint16_t *) (addr)) = (val)
|
||||
-# define put32u(addr, val) *((uint32_t *) (addr)) = (val)
|
||||
-#else
|
||||
-/* Distinguish between big endian and little endian. */
|
||||
-# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
-# define get16u(addr) \
|
||||
- (((const unsigned char *) (addr))[1] << 8 \
|
||||
- | ((const unsigned char *) (addr))[0])
|
||||
-# define get32u(addr) \
|
||||
- (((((const unsigned char *) (addr))[3] << 8 \
|
||||
- | ((const unsigned char *) (addr))[2]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[1]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[0])
|
||||
-
|
||||
-# define put16u(addr, val) \
|
||||
- ({ uint16_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- ((unsigned char *) (addr))[1] = __val >> 8; \
|
||||
- (void) 0; })
|
||||
-# define put32u(addr, val) \
|
||||
- ({ uint32_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[2] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[3] = __val; \
|
||||
- (void) 0; })
|
||||
-# else
|
||||
-# define get16u(addr) \
|
||||
- (((const unsigned char *) (addr))[0] << 8 \
|
||||
- | ((const unsigned char *) (addr))[1])
|
||||
-# define get32u(addr) \
|
||||
- (((((const unsigned char *) (addr))[0] << 8 \
|
||||
- | ((const unsigned char *) (addr))[1]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[2]) << 8 \
|
||||
- | ((const unsigned char *) (addr))[3])
|
||||
-
|
||||
-# define put16u(addr, val) \
|
||||
- ({ uint16_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- ((unsigned char *) (addr))[0] = __val >> 8; \
|
||||
- (void) 0; })
|
||||
-# define put32u(addr, val) \
|
||||
- ({ uint32_t __val = (val); \
|
||||
- ((unsigned char *) (addr))[3] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[2] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[1] = __val; \
|
||||
- __val >>= 8; \
|
||||
- ((unsigned char *) (addr))[0] = __val; \
|
||||
- (void) 0; })
|
||||
-# endif
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
/* For conversions from a fixed width character set to another fixed width
|
||||
character set we can define RESET_INPUT_BUFFER in a very fast way. */
|
||||
#if !defined RESET_INPUT_BUFFER && !defined SAVE_RESET_STATE
|
||||
diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c
|
||||
index a2b33b171e56392a..122e4593c5f6a0b4 100644
|
||||
--- a/iconvdata/iso-2022-jp-3.c
|
||||
+++ b/iconvdata/iso-2022-jp-3.c
|
||||
@@ -93,7 +93,7 @@ enum
|
||||
if (__glibc_likely (outbuf + 4 <= outend)) \
|
||||
{ \
|
||||
/* Write out the last character. */ \
|
||||
- put32u (outbuf, ch); \
|
||||
+ put32 (outbuf, ch); \
|
||||
outbuf += 4; \
|
||||
data->__statep->__count &= 7; \
|
||||
data->__statep->__count |= ASCII_set; \
|
||||
diff --git a/iconvdata/unicode.c b/iconvdata/unicode.c
|
||||
index d0db4239093fd33f..9b17e3a355e7f8a6 100644
|
||||
--- a/iconvdata/unicode.c
|
||||
+++ b/iconvdata/unicode.c
|
||||
@@ -52,10 +52,10 @@
|
||||
return (inptr == inend \
|
||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||
\
|
||||
- if (get16u (inptr) == BOM) \
|
||||
+ if (get16 (inptr) == BOM) \
|
||||
/* Simply ignore the BOM character. */ \
|
||||
*inptrp = inptr += 2; \
|
||||
- else if (get16u (inptr) == BOM_OE) \
|
||||
+ else if (get16 (inptr) == BOM_OE) \
|
||||
{ \
|
||||
data->__flags |= __GCONV_SWAP; \
|
||||
*inptrp = inptr += 2; \
|
||||
@@ -68,7 +68,7 @@
|
||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put16u (outbuf, BOM); \
|
||||
+ put16 (outbuf, BOM); \
|
||||
outbuf += 2; \
|
||||
} \
|
||||
swap = data->__flags & __GCONV_SWAP;
|
||||
diff --git a/iconvdata/utf-16.c b/iconvdata/utf-16.c
|
||||
index ed5f5b2f1f350ddf..6e714928fee8bdca 100644
|
||||
--- a/iconvdata/utf-16.c
|
||||
+++ b/iconvdata/utf-16.c
|
||||
@@ -56,10 +56,10 @@
|
||||
return (inptr == inend \
|
||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||
\
|
||||
- if (get16u (inptr) == BOM) \
|
||||
+ if (get16 (inptr) == BOM) \
|
||||
/* Simply ignore the BOM character. */ \
|
||||
*inptrp = inptr += 2; \
|
||||
- else if (get16u (inptr) == BOM_OE) \
|
||||
+ else if (get16 (inptr) == BOM_OE) \
|
||||
{ \
|
||||
data->__flags |= __GCONV_SWAP; \
|
||||
*inptrp = inptr += 2; \
|
||||
@@ -71,7 +71,7 @@
|
||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put16u (outbuf, BOM); \
|
||||
+ put16 (outbuf, BOM); \
|
||||
outbuf += 2; \
|
||||
} \
|
||||
} \
|
||||
diff --git a/iconvdata/utf-32.c b/iconvdata/utf-32.c
|
||||
index 7ed0e9bdec672683..dada94f2cca3b752 100644
|
||||
--- a/iconvdata/utf-32.c
|
||||
+++ b/iconvdata/utf-32.c
|
||||
@@ -52,10 +52,10 @@
|
||||
return (inptr == inend \
|
||||
? __GCONV_EMPTY_INPUT : __GCONV_INCOMPLETE_INPUT); \
|
||||
\
|
||||
- if (get32u (inptr) == BOM) \
|
||||
+ if (get32 (inptr) == BOM) \
|
||||
/* Simply ignore the BOM character. */ \
|
||||
*inptrp = inptr += 4; \
|
||||
- else if (get32u (inptr) == BOM_OE) \
|
||||
+ else if (get32 (inptr) == BOM_OE) \
|
||||
{ \
|
||||
data->__flags |= __GCONV_SWAP; \
|
||||
*inptrp = inptr += 4; \
|
||||
@@ -69,7 +69,7 @@
|
||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put32u (outbuf, BOM); \
|
||||
+ put32 (outbuf, BOM); \
|
||||
outbuf += 4; \
|
||||
} \
|
||||
else if (__builtin_expect (data->__invocation_counter == 0, 0) \
|
||||
diff --git a/sysdeps/s390/utf16-utf32-z9.c b/sysdeps/s390/utf16-utf32-z9.c
|
||||
index 27086d3e8a1f44ed..4f0d09ab94da59b5 100644
|
||||
--- a/sysdeps/s390/utf16-utf32-z9.c
|
||||
+++ b/sysdeps/s390/utf16-utf32-z9.c
|
||||
@@ -177,7 +177,7 @@ gconv_end (struct __gconv_step *data)
|
||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put16u (outbuf, BOM_UTF16); \
|
||||
+ put16 (outbuf, BOM_UTF16); \
|
||||
outbuf += 2; \
|
||||
} \
|
||||
else \
|
||||
@@ -186,7 +186,7 @@ gconv_end (struct __gconv_step *data)
|
||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put32u (outbuf, BOM_UTF32); \
|
||||
+ put32 (outbuf, BOM_UTF32); \
|
||||
outbuf += 4; \
|
||||
} \
|
||||
}
|
||||
diff --git a/sysdeps/s390/utf8-utf16-z9.c b/sysdeps/s390/utf8-utf16-z9.c
|
||||
index 409d64c578baa623..8e361890e4ea4ba4 100644
|
||||
--- a/sysdeps/s390/utf8-utf16-z9.c
|
||||
+++ b/sysdeps/s390/utf8-utf16-z9.c
|
||||
@@ -217,7 +217,7 @@ gconv_end (struct __gconv_step *data)
|
||||
if (__glibc_unlikely (outbuf + 2 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put16u (outbuf, BOM_UTF16); \
|
||||
+ put16 (outbuf, BOM_UTF16); \
|
||||
outbuf += 2; \
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/s390/utf8-utf32-z9.c b/sysdeps/s390/utf8-utf32-z9.c
|
||||
index c09d9b5bbde46e4d..422a999bfb690187 100644
|
||||
--- a/sysdeps/s390/utf8-utf32-z9.c
|
||||
+++ b/sysdeps/s390/utf8-utf32-z9.c
|
||||
@@ -217,7 +217,7 @@ gconv_end (struct __gconv_step *data)
|
||||
if (__glibc_unlikely (outbuf + 4 > outend)) \
|
||||
return __GCONV_FULL_OUTPUT; \
|
||||
\
|
||||
- put32u (outbuf, BOM); \
|
||||
+ put32 (outbuf, BOM); \
|
||||
outbuf += 4; \
|
||||
}
|
||||
|
||||
700
SOURCES/glibc-RHEL-162891-3.patch
Normal file
700
SOURCES/glibc-RHEL-162891-3.patch
Normal file
@ -0,0 +1,700 @@
|
||||
commit 3e20ddade31d9c392d8ccf7ec902172f4bb01c2b
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Feb 10 16:37:36 2023 -0300
|
||||
|
||||
iconv: Remove _STRING_ARCH_unaligned usage
|
||||
|
||||
Use put/get macros __builtin_bswap32 instead. It allows to remove
|
||||
the unaligned routines, the compiler will generate unaligned access
|
||||
if the ABI allows it.
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
|
||||
|
||||
Conflicts:
|
||||
iconv/gconv_simple.c
|
||||
(fixup context)
|
||||
iconv/loop.c
|
||||
(fixup context)
|
||||
iconv/skeleton.c
|
||||
(fixup context)
|
||||
|
||||
diff --git a/iconv/gconv_simple.c b/iconv/gconv_simple.c
|
||||
index 506c92caf228d61f..d95a5e75e3cd80f1 100644
|
||||
--- a/iconv/gconv_simple.c
|
||||
+++ b/iconv/gconv_simple.c
|
||||
@@ -87,68 +87,22 @@ internal_ucs4_loop (struct __gconv_step *step,
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
/* Sigh, we have to do some real work. */
|
||||
size_t cnt;
|
||||
- uint32_t *outptr32 = (uint32_t *) outptr;
|
||||
-
|
||||
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
- *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = (unsigned char *) outptr32;
|
||||
-#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
- /* Simply copy the data. */
|
||||
- *inptrp = inptr + n_convert * 4;
|
||||
- *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
|
||||
-#else
|
||||
-# error "This endianess is not supported."
|
||||
-#endif
|
||||
-
|
||||
- /* Determine the status. */
|
||||
- if (*inptrp == inend)
|
||||
- result = __GCONV_EMPTY_INPUT;
|
||||
- else if (*outptrp + 4 > outend)
|
||||
- result = __GCONV_FULL_OUTPUT;
|
||||
- else
|
||||
- result = __GCONV_INCOMPLETE_INPUT;
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-
|
||||
-#if !_STRING_ARCH_unaligned
|
||||
-static inline int
|
||||
-__attribute ((always_inline))
|
||||
-internal_ucs4_loop_unaligned (struct __gconv_step *step,
|
||||
- struct __gconv_step_data *step_data,
|
||||
- const unsigned char **inptrp,
|
||||
- const unsigned char *inend,
|
||||
- unsigned char **outptrp, unsigned char *outend,
|
||||
- size_t *irreversible)
|
||||
-{
|
||||
- const unsigned char *inptr = *inptrp;
|
||||
- unsigned char *outptr = *outptrp;
|
||||
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
||||
- int result;
|
||||
-
|
||||
-# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
- /* Sigh, we have to do some real work. */
|
||||
- size_t cnt;
|
||||
|
||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
||||
{
|
||||
- outptr[0] = inptr[3];
|
||||
- outptr[1] = inptr[2];
|
||||
- outptr[2] = inptr[1];
|
||||
- outptr[3] = inptr[0];
|
||||
+ uint32_t val = get32 (inptr);
|
||||
+ put32 (outptr, __builtin_bswap32 (val));
|
||||
}
|
||||
|
||||
*inptrp = inptr;
|
||||
*outptrp = outptr;
|
||||
-# elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
+#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
/* Simply copy the data. */
|
||||
*inptrp = inptr + n_convert * 4;
|
||||
*outptrp = __mempcpy (outptr, inptr, n_convert * 4);
|
||||
-# else
|
||||
-# error "This endianess is not supported."
|
||||
-# endif
|
||||
+#else
|
||||
+# error "This endianess is not supported."
|
||||
+#endif
|
||||
|
||||
/* Determine the status. */
|
||||
if (*inptrp == inend)
|
||||
@@ -160,8 +114,6 @@ internal_ucs4_loop_unaligned (struct __gconv_step *step,
|
||||
|
||||
return result;
|
||||
}
|
||||
-#endif
|
||||
-
|
||||
|
||||
static inline int
|
||||
__attribute ((always_inline))
|
||||
@@ -243,12 +195,9 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||
|
||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
{
|
||||
- uint32_t inval;
|
||||
-
|
||||
+ uint32_t inval = get32 (inptr);
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
- inval = bswap_32 (*(const uint32_t *) inptr);
|
||||
-#else
|
||||
- inval = *(const uint32_t *) inptr;
|
||||
+ inval = __builtin_bswap32 (inval);
|
||||
#endif
|
||||
|
||||
if (__glibc_unlikely (inval > 0x7fffffff))
|
||||
@@ -273,7 +222,7 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||
return __GCONV_ILLEGAL_INPUT;
|
||||
}
|
||||
|
||||
- *((uint32_t *) outptr) = inval;
|
||||
+ put32 (outptr, inval);
|
||||
outptr += sizeof (uint32_t);
|
||||
}
|
||||
|
||||
@@ -291,77 +240,6 @@ ucs4_internal_loop (struct __gconv_step *step,
|
||||
return result;
|
||||
}
|
||||
|
||||
-#if !_STRING_ARCH_unaligned
|
||||
-static inline int
|
||||
-__attribute ((always_inline))
|
||||
-ucs4_internal_loop_unaligned (struct __gconv_step *step,
|
||||
- struct __gconv_step_data *step_data,
|
||||
- const unsigned char **inptrp,
|
||||
- const unsigned char *inend,
|
||||
- unsigned char **outptrp, unsigned char *outend,
|
||||
- size_t *irreversible)
|
||||
-{
|
||||
- int flags = step_data->__flags;
|
||||
- const unsigned char *inptr = *inptrp;
|
||||
- unsigned char *outptr = *outptrp;
|
||||
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
||||
- int result;
|
||||
- size_t cnt;
|
||||
-
|
||||
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
- {
|
||||
- if (__glibc_unlikely (inptr[0] > 0x80))
|
||||
- {
|
||||
- /* The value is too large. We don't try transliteration here since
|
||||
- this is not an error because of the lack of possibilities to
|
||||
- represent the result. This is a genuine bug in the input since
|
||||
- UCS4 does not allow such values. */
|
||||
- if (irreversible == NULL)
|
||||
- /* We are transliterating, don't try to correct anything. */
|
||||
- return __GCONV_ILLEGAL_INPUT;
|
||||
-
|
||||
- if (flags & __GCONV_IGNORE_ERRORS)
|
||||
- {
|
||||
- /* Just ignore this character. */
|
||||
- ++*irreversible;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = outptr;
|
||||
- return __GCONV_ILLEGAL_INPUT;
|
||||
- }
|
||||
-
|
||||
-# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
- outptr[3] = inptr[0];
|
||||
- outptr[2] = inptr[1];
|
||||
- outptr[1] = inptr[2];
|
||||
- outptr[0] = inptr[3];
|
||||
-# else
|
||||
- outptr[0] = inptr[0];
|
||||
- outptr[1] = inptr[1];
|
||||
- outptr[2] = inptr[2];
|
||||
- outptr[3] = inptr[3];
|
||||
-# endif
|
||||
- outptr += 4;
|
||||
- }
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = outptr;
|
||||
-
|
||||
- /* Determine the status. */
|
||||
- if (*inptrp == inend)
|
||||
- result = __GCONV_EMPTY_INPUT;
|
||||
- else if (*outptrp + 4 > outend)
|
||||
- result = __GCONV_FULL_OUTPUT;
|
||||
- else
|
||||
- result = __GCONV_INCOMPLETE_INPUT;
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
static inline int
|
||||
__attribute ((always_inline))
|
||||
ucs4_internal_loop_single (struct __gconv_step *step,
|
||||
@@ -454,11 +332,12 @@ internal_ucs4le_loop (struct __gconv_step *step,
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
/* Sigh, we have to do some real work. */
|
||||
size_t cnt;
|
||||
- uint32_t *outptr32 = (uint32_t *) outptr;
|
||||
|
||||
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
- *outptr32++ = bswap_32 (*(const uint32_t *) inptr);
|
||||
- outptr = (unsigned char *) outptr32;
|
||||
+ for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
||||
+ {
|
||||
+ uint32_t val = get32 (inptr);
|
||||
+ put32 (outptr, __builtin_bswap32 (val));
|
||||
+ }
|
||||
|
||||
*inptrp = inptr;
|
||||
*outptrp = outptr;
|
||||
@@ -481,59 +360,6 @@ internal_ucs4le_loop (struct __gconv_step *step,
|
||||
return result;
|
||||
}
|
||||
|
||||
-#if !_STRING_ARCH_unaligned
|
||||
-static inline int
|
||||
-__attribute ((always_inline))
|
||||
-internal_ucs4le_loop_unaligned (struct __gconv_step *step,
|
||||
- struct __gconv_step_data *step_data,
|
||||
- const unsigned char **inptrp,
|
||||
- const unsigned char *inend,
|
||||
- unsigned char **outptrp, unsigned char *outend,
|
||||
- size_t *irreversible)
|
||||
-{
|
||||
- const unsigned char *inptr = *inptrp;
|
||||
- unsigned char *outptr = *outptrp;
|
||||
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
||||
- int result;
|
||||
-
|
||||
-# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
- /* Sigh, we have to do some real work. */
|
||||
- size_t cnt;
|
||||
-
|
||||
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4, outptr += 4)
|
||||
- {
|
||||
- outptr[0] = inptr[3];
|
||||
- outptr[1] = inptr[2];
|
||||
- outptr[2] = inptr[1];
|
||||
- outptr[3] = inptr[0];
|
||||
- }
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = outptr;
|
||||
-# elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
- /* Simply copy the data. */
|
||||
- *inptrp = inptr + n_convert * 4;
|
||||
- *outptrp = __mempcpy (outptr, inptr, n_convert * 4);
|
||||
-# else
|
||||
-# error "This endianess is not supported."
|
||||
-# endif
|
||||
-
|
||||
- /* Determine the status. */
|
||||
- if (*inptrp == inend)
|
||||
- result = __GCONV_EMPTY_INPUT;
|
||||
- else if (*inptrp + 4 > inend)
|
||||
- result = __GCONV_INCOMPLETE_INPUT;
|
||||
- else
|
||||
- {
|
||||
- assert (*outptrp + 4 > outend);
|
||||
- result = __GCONV_FULL_OUTPUT;
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
static inline int
|
||||
__attribute ((always_inline))
|
||||
internal_ucs4le_loop_single (struct __gconv_step *step,
|
||||
@@ -613,12 +439,9 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||
|
||||
for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
{
|
||||
- uint32_t inval;
|
||||
-
|
||||
+ uint32_t inval = get32 (inptr);
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
- inval = bswap_32 (*(const uint32_t *) inptr);
|
||||
-#else
|
||||
- inval = *(const uint32_t *) inptr;
|
||||
+ inval = __builtin_bswap32 (inval);
|
||||
#endif
|
||||
|
||||
if (__glibc_unlikely (inval > 0x7fffffff))
|
||||
@@ -643,7 +466,7 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||
return __GCONV_ILLEGAL_INPUT;
|
||||
}
|
||||
|
||||
- *((uint32_t *) outptr) = inval;
|
||||
+ put32 (outptr, inval);
|
||||
outptr += sizeof (uint32_t);
|
||||
}
|
||||
|
||||
@@ -664,81 +487,6 @@ ucs4le_internal_loop (struct __gconv_step *step,
|
||||
return result;
|
||||
}
|
||||
|
||||
-#if !_STRING_ARCH_unaligned
|
||||
-static inline int
|
||||
-__attribute ((always_inline))
|
||||
-ucs4le_internal_loop_unaligned (struct __gconv_step *step,
|
||||
- struct __gconv_step_data *step_data,
|
||||
- const unsigned char **inptrp,
|
||||
- const unsigned char *inend,
|
||||
- unsigned char **outptrp, unsigned char *outend,
|
||||
- size_t *irreversible)
|
||||
-{
|
||||
- int flags = step_data->__flags;
|
||||
- const unsigned char *inptr = *inptrp;
|
||||
- unsigned char *outptr = *outptrp;
|
||||
- size_t n_convert = MIN (inend - inptr, outend - outptr) / 4;
|
||||
- int result;
|
||||
- size_t cnt;
|
||||
-
|
||||
- for (cnt = 0; cnt < n_convert; ++cnt, inptr += 4)
|
||||
- {
|
||||
- if (__glibc_unlikely (inptr[3] > 0x80))
|
||||
- {
|
||||
- /* The value is too large. We don't try transliteration here since
|
||||
- this is not an error because of the lack of possibilities to
|
||||
- represent the result. This is a genuine bug in the input since
|
||||
- UCS4 does not allow such values. */
|
||||
- if (irreversible == NULL)
|
||||
- /* We are transliterating, don't try to correct anything. */
|
||||
- return __GCONV_ILLEGAL_INPUT;
|
||||
-
|
||||
- if (flags & __GCONV_IGNORE_ERRORS)
|
||||
- {
|
||||
- /* Just ignore this character. */
|
||||
- ++*irreversible;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = outptr;
|
||||
- return __GCONV_ILLEGAL_INPUT;
|
||||
- }
|
||||
-
|
||||
-# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
- outptr[3] = inptr[0];
|
||||
- outptr[2] = inptr[1];
|
||||
- outptr[1] = inptr[2];
|
||||
- outptr[0] = inptr[3];
|
||||
-# else
|
||||
- outptr[0] = inptr[0];
|
||||
- outptr[1] = inptr[1];
|
||||
- outptr[2] = inptr[2];
|
||||
- outptr[3] = inptr[3];
|
||||
-# endif
|
||||
-
|
||||
- outptr += 4;
|
||||
- }
|
||||
-
|
||||
- *inptrp = inptr;
|
||||
- *outptrp = outptr;
|
||||
-
|
||||
- /* Determine the status. */
|
||||
- if (*inptrp == inend)
|
||||
- result = __GCONV_EMPTY_INPUT;
|
||||
- else if (*inptrp + 4 > inend)
|
||||
- result = __GCONV_INCOMPLETE_INPUT;
|
||||
- else
|
||||
- {
|
||||
- assert (*outptrp + 4 > outend);
|
||||
- result = __GCONV_FULL_OUTPUT;
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-
|
||||
static inline int
|
||||
__attribute ((always_inline))
|
||||
ucs4le_internal_loop_single (struct __gconv_step *step,
|
||||
diff --git a/iconv/loop.c b/iconv/loop.c
|
||||
index a9aa201eadc07bd9..9ef2657f4cbe051c 100644
|
||||
--- a/iconv/loop.c
|
||||
+++ b/iconv/loop.c
|
||||
@@ -59,12 +59,7 @@
|
||||
#include <libc-diag.h>
|
||||
|
||||
#undef FCTNAME2
|
||||
-#if _STRING_ARCH_unaligned || !defined DEFINE_UNALIGNED
|
||||
-# define FCTNAME2(name) name
|
||||
-#else
|
||||
-# define FCTNAME2(name) name##_unaligned
|
||||
-#endif
|
||||
-#define FCTNAME(name) FCTNAME2(name)
|
||||
+#define FCTNAME(name) name
|
||||
|
||||
|
||||
/* We need at least one byte for the next round. */
|
||||
@@ -280,20 +275,9 @@ FCTNAME (LOOPFCT) (struct __gconv_step *step,
|
||||
}
|
||||
|
||||
|
||||
-/* Include the file a second time to define the function to handle
|
||||
- unaligned access. */
|
||||
-#if !defined DEFINE_UNALIGNED && !_STRING_ARCH_unaligned \
|
||||
- && MIN_NEEDED_INPUT != 1 && MAX_NEEDED_INPUT % MIN_NEEDED_INPUT == 0 \
|
||||
- && MIN_NEEDED_OUTPUT != 1 && MAX_NEEDED_OUTPUT % MIN_NEEDED_OUTPUT == 0
|
||||
-# undef unaligned
|
||||
-
|
||||
-# define DEFINE_UNALIGNED
|
||||
-# include "loop.c"
|
||||
-# undef DEFINE_UNALIGNED
|
||||
-#else
|
||||
-# if MAX_NEEDED_INPUT > 1
|
||||
-# define SINGLE(fct) SINGLE2 (fct)
|
||||
-# define SINGLE2(fct) fct##_single
|
||||
+#if MAX_NEEDED_INPUT > 1
|
||||
+# define SINGLE(fct) SINGLE2 (fct)
|
||||
+# define SINGLE2(fct) fct##_single
|
||||
static inline int
|
||||
__attribute ((always_inline))
|
||||
SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
@@ -303,37 +287,37 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
size_t *irreversible EXTRA_LOOP_DECLS)
|
||||
{
|
||||
mbstate_t *state = step_data->__statep;
|
||||
-# ifdef LOOP_NEED_FLAGS
|
||||
+# ifdef LOOP_NEED_FLAGS
|
||||
int flags = step_data->__flags;
|
||||
-# endif
|
||||
-# ifdef LOOP_NEED_DATA
|
||||
+# endif
|
||||
+# ifdef LOOP_NEED_DATA
|
||||
void *data = step->__data;
|
||||
-# endif
|
||||
+# endif
|
||||
int result = __GCONV_OK;
|
||||
unsigned char bytebuf[MAX_NEEDED_INPUT];
|
||||
const unsigned char *inptr = *inptrp;
|
||||
unsigned char *outptr = *outptrp;
|
||||
size_t inlen;
|
||||
|
||||
-# ifdef INIT_PARAMS
|
||||
+# ifdef INIT_PARAMS
|
||||
INIT_PARAMS;
|
||||
-# endif
|
||||
+# endif
|
||||
|
||||
-# ifdef UNPACK_BYTES
|
||||
+# ifdef UNPACK_BYTES
|
||||
UNPACK_BYTES
|
||||
-# else
|
||||
+# else
|
||||
/* Add the bytes from the state to the input buffer. */
|
||||
assert ((state->__count & 7) <= sizeof (state->__value));
|
||||
for (inlen = 0; inlen < (size_t) (state->__count & 7); ++inlen)
|
||||
bytebuf[inlen] = state->__value.__wchb[inlen];
|
||||
-# endif
|
||||
+# endif
|
||||
|
||||
/* Are there enough bytes in the input buffer? */
|
||||
if (MIN_NEEDED_INPUT > 1
|
||||
&& __builtin_expect (inptr + (MIN_NEEDED_INPUT - inlen) > inend, 0))
|
||||
{
|
||||
*inptrp = inend;
|
||||
-# ifdef STORE_REST
|
||||
+# ifdef STORE_REST
|
||||
|
||||
/* Building with -O3 GCC emits a `array subscript is above array
|
||||
bounds' warning. GCC BZ #64739 has been opened for this. */
|
||||
@@ -348,12 +332,12 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
inend = &bytebuf[inlen];
|
||||
|
||||
STORE_REST
|
||||
-# else
|
||||
+# else
|
||||
/* We don't have enough input for another complete input
|
||||
character. */
|
||||
while (inptr < inend)
|
||||
state->__value.__wchb[inlen++] = *inptr++;
|
||||
-# endif
|
||||
+# endif
|
||||
|
||||
return __GCONV_INCOMPLETE_INPUT;
|
||||
}
|
||||
@@ -393,11 +377,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
result = __GCONV_OK;
|
||||
|
||||
/* Clear the state buffer. */
|
||||
-# ifdef CLEAR_STATE
|
||||
+# ifdef CLEAR_STATE
|
||||
CLEAR_STATE;
|
||||
-# else
|
||||
+# else
|
||||
state->__count &= ~7;
|
||||
-# endif
|
||||
+# endif
|
||||
}
|
||||
else if (result == __GCONV_INCOMPLETE_INPUT)
|
||||
{
|
||||
@@ -406,11 +390,11 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
assert (inend != &bytebuf[MAX_NEEDED_INPUT]);
|
||||
|
||||
*inptrp += inend - bytebuf - (state->__count & 7);
|
||||
-# ifdef STORE_REST
|
||||
+# ifdef STORE_REST
|
||||
inptrp = &inptr;
|
||||
|
||||
STORE_REST
|
||||
-# else
|
||||
+# else
|
||||
/* We don't have enough input for another complete input
|
||||
character. */
|
||||
assert (inend - inptr > (state->__count & ~7));
|
||||
@@ -419,14 +403,13 @@ SINGLE(LOOPFCT) (struct __gconv_step *step,
|
||||
inlen = 0;
|
||||
while (inptr < inend)
|
||||
state->__value.__wchb[inlen++] = *inptr++;
|
||||
-# endif
|
||||
+# endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
-# undef SINGLE
|
||||
-# undef SINGLE2
|
||||
-# endif
|
||||
+# undef SINGLE
|
||||
+# undef SINGLE2
|
||||
|
||||
|
||||
# ifdef ONEBYTE_BODY
|
||||
@@ -458,4 +441,3 @@ gconv_btowc (struct __gconv_step *step, unsigned char c)
|
||||
#undef LOOP_NEED_STATE
|
||||
#undef LOOP_NEED_FLAGS
|
||||
#undef LOOP_NEED_DATA
|
||||
-#undef unaligned
|
||||
diff --git a/iconv/skeleton.c b/iconv/skeleton.c
|
||||
index 4f20a009d7ffb1db..bf2855c84f0270cd 100644
|
||||
--- a/iconv/skeleton.c
|
||||
+++ b/iconv/skeleton.c
|
||||
@@ -446,33 +446,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||
size_t lirreversible = 0;
|
||||
size_t *lirreversiblep = irreversible ? &lirreversible : NULL;
|
||||
|
||||
- /* The following assumes that encodings, which have a variable length
|
||||
- what might unalign a buffer even though it is an aligned in the
|
||||
- beginning, either don't have the minimal number of bytes as a divisor
|
||||
- of the maximum length or have a minimum length of 1. This is true
|
||||
- for all known and supported encodings.
|
||||
- We use && instead of || to combine the subexpression for the FROM
|
||||
- encoding and for the TO encoding, because usually one of them is
|
||||
- INTERNAL, for which the subexpression evaluates to 1, but INTERNAL
|
||||
- buffers are always aligned correctly. */
|
||||
-#define POSSIBLY_UNALIGNED \
|
||||
- (!_STRING_ARCH_unaligned \
|
||||
- && (((FROM_LOOP_MIN_NEEDED_FROM != 1 \
|
||||
- && FROM_LOOP_MAX_NEEDED_FROM % FROM_LOOP_MIN_NEEDED_FROM == 0) \
|
||||
- && (FROM_LOOP_MIN_NEEDED_TO != 1 \
|
||||
- && FROM_LOOP_MAX_NEEDED_TO % FROM_LOOP_MIN_NEEDED_TO == 0)) \
|
||||
- || ((TO_LOOP_MIN_NEEDED_FROM != 1 \
|
||||
- && TO_LOOP_MAX_NEEDED_FROM % TO_LOOP_MIN_NEEDED_FROM == 0) \
|
||||
- && (TO_LOOP_MIN_NEEDED_TO != 1 \
|
||||
- && TO_LOOP_MAX_NEEDED_TO % TO_LOOP_MIN_NEEDED_TO == 0))))
|
||||
-#if POSSIBLY_UNALIGNED
|
||||
- int unaligned;
|
||||
-# define GEN_unaligned(name) GEN_unaligned2 (name)
|
||||
-# define GEN_unaligned2(name) name##_unaligned
|
||||
-#else
|
||||
-# define unaligned 0
|
||||
-#endif
|
||||
-
|
||||
#ifdef PREPARE_LOOP
|
||||
PREPARE_LOOP
|
||||
#endif
|
||||
@@ -512,18 +485,6 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||
}
|
||||
#endif
|
||||
|
||||
-#if POSSIBLY_UNALIGNED
|
||||
- unaligned =
|
||||
- ((FROM_DIRECTION
|
||||
- && ((uintptr_t) inptr % FROM_LOOP_MIN_NEEDED_FROM != 0
|
||||
- || ((data->__flags & __GCONV_IS_LAST)
|
||||
- && (uintptr_t) outbuf % FROM_LOOP_MIN_NEEDED_TO != 0)))
|
||||
- || (!FROM_DIRECTION
|
||||
- && (((data->__flags & __GCONV_IS_LAST)
|
||||
- && (uintptr_t) outbuf % TO_LOOP_MIN_NEEDED_TO != 0)
|
||||
- || (uintptr_t) inptr % TO_LOOP_MIN_NEEDED_FROM != 0)));
|
||||
-#endif
|
||||
-
|
||||
while (1)
|
||||
{
|
||||
/* Remember the start value for this round. */
|
||||
@@ -535,34 +496,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||
SAVE_RESET_STATE (1);
|
||||
#endif
|
||||
|
||||
- if (__glibc_likely (!unaligned))
|
||||
- {
|
||||
- if (FROM_DIRECTION)
|
||||
- /* Run the conversion loop. */
|
||||
- status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
- lirreversiblep EXTRA_LOOP_ARGS);
|
||||
- else
|
||||
- /* Run the conversion loop. */
|
||||
- status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
- lirreversiblep EXTRA_LOOP_ARGS);
|
||||
- }
|
||||
-#if POSSIBLY_UNALIGNED
|
||||
+ if (FROM_DIRECTION)
|
||||
+ /* Run the conversion loop. */
|
||||
+ status = FROM_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
+ lirreversiblep EXTRA_LOOP_ARGS);
|
||||
else
|
||||
- {
|
||||
- if (FROM_DIRECTION)
|
||||
- /* Run the conversion loop. */
|
||||
- status = GEN_unaligned (FROM_LOOP) (step, data, inptrp, inend,
|
||||
- &outbuf, outend,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- else
|
||||
- /* Run the conversion loop. */
|
||||
- status = GEN_unaligned (TO_LOOP) (step, data, inptrp, inend,
|
||||
- &outbuf, outend,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- }
|
||||
-#endif
|
||||
+ /* Run the conversion loop. */
|
||||
+ status = TO_LOOP (step, data, inptrp, inend, &outbuf, outend,
|
||||
+ lirreversiblep EXTRA_LOOP_ARGS);
|
||||
|
||||
/* If we were called as part of an error handling module we
|
||||
don't do anything else here. */
|
||||
@@ -619,41 +560,14 @@ FUNCTION_NAME (struct __gconv_step *step, struct __gconv_step_data *data,
|
||||
SAVE_RESET_STATE (0);
|
||||
# endif
|
||||
|
||||
- if (__glibc_likely (!unaligned))
|
||||
- {
|
||||
- if (FROM_DIRECTION)
|
||||
- /* Run the conversion loop. */
|
||||
- nstatus = FROM_LOOP (step, data, inptrp, inend,
|
||||
- &outbuf, outerr,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- else
|
||||
- /* Run the conversion loop. */
|
||||
- nstatus = TO_LOOP (step, data, inptrp, inend,
|
||||
- &outbuf, outerr,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- }
|
||||
-# if POSSIBLY_UNALIGNED
|
||||
+ if (FROM_DIRECTION)
|
||||
+ /* Run the conversion loop. */
|
||||
+ nstatus = FROM_LOOP (step, data, inptrp, inend,
|
||||
+ &outbuf, outerr, lirreversiblep EXTRA_LOOP_ARGS);
|
||||
else
|
||||
- {
|
||||
- if (FROM_DIRECTION)
|
||||
- /* Run the conversion loop. */
|
||||
- nstatus = GEN_unaligned (FROM_LOOP) (step, data,
|
||||
- inptrp, inend,
|
||||
- &outbuf,
|
||||
- outerr,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- else
|
||||
- /* Run the conversion loop. */
|
||||
- nstatus = GEN_unaligned (TO_LOOP) (step, data,
|
||||
- inptrp, inend,
|
||||
- &outbuf, outerr,
|
||||
- lirreversiblep
|
||||
- EXTRA_LOOP_ARGS);
|
||||
- }
|
||||
-# endif
|
||||
+ /* Run the conversion loop. */
|
||||
+ nstatus = TO_LOOP (step, data, inptrp, inend, &outbuf,
|
||||
+ outerr, lirreversiblep EXTRA_LOOP_ARGS);
|
||||
|
||||
/* We must run out of output buffer space in this
|
||||
rerun. */
|
||||
325
SOURCES/glibc-RHEL-162891-4.patch
Normal file
325
SOURCES/glibc-RHEL-162891-4.patch
Normal file
@ -0,0 +1,325 @@
|
||||
commit d6f08d1cf027f4eb2ba289a6cc66853722d4badc
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Apr 16 19:13:43 2026 +0200
|
||||
|
||||
Use pending character state in IBM1390, IBM1399 character sets (CVE-2026-4046)
|
||||
|
||||
Follow the example in iso-2022-jp-3.c and use the __count state
|
||||
variable to store the pending character. This avoids restarting
|
||||
the conversion if the output buffer ends between two 4-byte UCS-4
|
||||
code points, so that the assert reported in the bug can no longer
|
||||
happen.
|
||||
|
||||
Even though the fix is applied to ibm1364.c, the change is only
|
||||
effective for the two HAS_COMBINED codecs for IBM1390, IBM1399.
|
||||
|
||||
The test case was mostly auto-generated using
|
||||
claude-4.6-opus-high-thinking, and composer-2-fast shows up in the
|
||||
log as well. During review, gpt-5.4-xhigh flagged that the original
|
||||
version of the test case was not exercising the new character
|
||||
flush logic.
|
||||
|
||||
This fixes bug 33980.
|
||||
|
||||
Assisted-by: LLM
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
iconvdata/Makefile
|
||||
(fixup context)
|
||||
|
||||
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||
index c959758a90ed954f..c4a7159488bbfdf2 100644
|
||||
--- a/iconvdata/Makefile
|
||||
+++ b/iconvdata/Makefile
|
||||
@@ -75,7 +75,7 @@ ifeq (yes,$(build-shared))
|
||||
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
|
||||
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
|
||||
bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \
|
||||
- bug-iconv15 tst-iconv-iso-2022-cn-ext
|
||||
+ bug-iconv15 tst-iconv-iso-2022-cn-ext tst-bug33980
|
||||
ifeq ($(have-thread-library),yes)
|
||||
tests += bug-iconv3
|
||||
endif
|
||||
@@ -327,6 +327,8 @@ $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
$(addprefix $(objpfx),$(modules.so))
|
||||
+$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \
|
||||
+ $(addprefix $(objpfx),$(modules.so))
|
||||
|
||||
$(objpfx)iconv-test.out: run-iconv-test.sh \
|
||||
$(addprefix $(objpfx), $(gconv-modules)) \
|
||||
diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
|
||||
index ecc3f8ddddbdbc8c..5edd9d01262a1c0d 100644
|
||||
--- a/iconvdata/ibm1364.c
|
||||
+++ b/iconvdata/ibm1364.c
|
||||
@@ -68,12 +68,29 @@
|
||||
|
||||
/* Since this is a stateful encoding we have to provide code which resets
|
||||
the output state to the initial state. This has to be done during the
|
||||
- flushing. */
|
||||
+ flushing. For the to-internal direction (FROM_DIRECTION is true),
|
||||
+ there may be a pending character that needs flushing. */
|
||||
#define EMIT_SHIFT_TO_INIT \
|
||||
if ((data->__statep->__count & ~7) != sb) \
|
||||
{ \
|
||||
if (FROM_DIRECTION) \
|
||||
- data->__statep->__count &= 7; \
|
||||
+ { \
|
||||
+ uint32_t ch = data->__statep->__count >> 7; \
|
||||
+ if (__glibc_unlikely (ch != 0)) \
|
||||
+ { \
|
||||
+ if (__glibc_unlikely (outend - outbuf < 4)) \
|
||||
+ status = __GCONV_FULL_OUTPUT; \
|
||||
+ else \
|
||||
+ { \
|
||||
+ put32 (outbuf, ch); \
|
||||
+ outbuf += 4; \
|
||||
+ /* Clear character and db bit. */ \
|
||||
+ data->__statep->__count &= 7; \
|
||||
+ } \
|
||||
+ } \
|
||||
+ else \
|
||||
+ data->__statep->__count &= 7; \
|
||||
+ } \
|
||||
else \
|
||||
{ \
|
||||
/* We are not in the initial state. To switch back we have \
|
||||
@@ -100,11 +117,13 @@
|
||||
*curcsp = save_curcs
|
||||
|
||||
|
||||
-/* Current codeset type. */
|
||||
+/* Current codeset type. The bit is stored in the __count variable of
|
||||
+ the conversion state. If the db bit is set, bit 7 and above store
|
||||
+ a pending UCS-4 code point if non-zero. */
|
||||
enum
|
||||
{
|
||||
- sb = 0,
|
||||
- db = 64
|
||||
+ sb = 0, /* Single byte mode. */
|
||||
+ db = 64 /* Double byte mode. */
|
||||
};
|
||||
|
||||
|
||||
@@ -120,21 +139,29 @@ enum
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
- /* This is a combined character. Make sure we have room. */ \
|
||||
- if (__glibc_unlikely (outptr + 8 > outend)) \
|
||||
- { \
|
||||
- result = __GCONV_FULL_OUTPUT; \
|
||||
- break; \
|
||||
- } \
|
||||
- \
|
||||
const struct divide *cmbp \
|
||||
= &DB_TO_UCS4_COMB[ch - __TO_UCS4_COMBINED_MIN]; \
|
||||
assert (cmbp->res1 != 0 && cmbp->res2 != 0); \
|
||||
\
|
||||
put32 (outptr, cmbp->res1); \
|
||||
outptr += 4; \
|
||||
- put32 (outptr, cmbp->res2); \
|
||||
- outptr += 4; \
|
||||
+ \
|
||||
+ /* See whether we have room for the second character. */ \
|
||||
+ if (outend - outptr >= 4) \
|
||||
+ { \
|
||||
+ put32 (outptr, cmbp->res2); \
|
||||
+ outptr += 4; \
|
||||
+ } \
|
||||
+ else \
|
||||
+ { \
|
||||
+ /* Otherwise store only the first character now, and \
|
||||
+ put the second one into the queue. */ \
|
||||
+ curcs |= cmbp->res2 << 7; \
|
||||
+ inptr += 2; \
|
||||
+ /* Tell the caller why we terminate the loop. */ \
|
||||
+ result = __GCONV_FULL_OUTPUT; \
|
||||
+ break; \
|
||||
+ } \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
@@ -154,7 +181,20 @@ enum
|
||||
#define LOOPFCT FROM_LOOP
|
||||
#define BODY \
|
||||
{ \
|
||||
- uint32_t ch = *inptr; \
|
||||
+ uint32_t ch; \
|
||||
+ \
|
||||
+ ch = curcs >> 7; \
|
||||
+ if (__glibc_unlikely (ch != 0)) \
|
||||
+ { \
|
||||
+ put32 (outptr, ch); \
|
||||
+ outptr += 4; \
|
||||
+ /* Remove the pending character, but preserve state bits. */ \
|
||||
+ curcs &= (1 << 7) - 1; \
|
||||
+ continue; \
|
||||
+ } \
|
||||
+ \
|
||||
+ /* Otherwise read the next input byte. */ \
|
||||
+ ch = *inptr; \
|
||||
\
|
||||
if (__builtin_expect (ch, 0) == SO) \
|
||||
{ \
|
||||
diff --git a/iconvdata/tst-bug33980.c b/iconvdata/tst-bug33980.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c9693e0efebe4eae
|
||||
--- /dev/null
|
||||
+++ b/iconvdata/tst-bug33980.c
|
||||
@@ -0,0 +1,153 @@
|
||||
+/* Test for bug 33980: combining characters in IBM1390/IBM1399.
|
||||
+ Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <alloc_buffer.h>
|
||||
+#include <errno.h>
|
||||
+#include <iconv.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+/* Run iconv in a loop with a small output buffer of OUTBUFSIZE bytes
|
||||
+ starting at OUTBUF. OUTBUF should be right before an unmapped page
|
||||
+ so that writing past the end will fault. Skip SHIFT bytes at the
|
||||
+ start of the input and output, to exercise different buffer
|
||||
+ alignment. TRUNCATE indicates skipped bytes at the end of
|
||||
+ input (0 and 1 a valid). */
|
||||
+static void
|
||||
+test_one (const char *encoding, unsigned int shift, unsigned int truncate,
|
||||
+ char *outbuf, size_t outbufsize)
|
||||
+{
|
||||
+ /* In IBM1390 and IBM1399, the DBCS code 0xECB5 expands to two
|
||||
+ Unicode code points when translated. */
|
||||
+ static char input[] =
|
||||
+ {
|
||||
+ /* 8 letters X. */
|
||||
+ 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
|
||||
+ /* SO, 0xECB5, SI: shift to DBCS, special character, shift back. */
|
||||
+ 0x0e, 0xec, 0xb5, 0x0f
|
||||
+ };
|
||||
+
|
||||
+ /* Expected output after UTF-8 conversion. */
|
||||
+ static char expected[] =
|
||||
+ {
|
||||
+ 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
|
||||
+ /* U+304B (HIRAGANA LETTER KA). */
|
||||
+ 0xe3, 0x81, 0x8b,
|
||||
+ /* U+309A (COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK). */
|
||||
+ 0xe3, 0x82, 0x9a
|
||||
+ };
|
||||
+
|
||||
+ iconv_t cd = iconv_open ("UTF-8", encoding);
|
||||
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
|
||||
+
|
||||
+ char result_storage[64];
|
||||
+ struct alloc_buffer result_buf
|
||||
+ = alloc_buffer_create (result_storage, sizeof (result_storage));
|
||||
+
|
||||
+ char *inptr = &input[shift];
|
||||
+ size_t inleft = sizeof (input) - shift - truncate;
|
||||
+
|
||||
+ while (inleft > 0)
|
||||
+ {
|
||||
+ char *outptr = outbuf;
|
||||
+ size_t outleft = outbufsize;
|
||||
+ size_t inleft_before = inleft;
|
||||
+
|
||||
+ size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);
|
||||
+ size_t produced = outptr - outbuf;
|
||||
+ alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
|
||||
+
|
||||
+ if (ret == (size_t) -1 && errno == E2BIG)
|
||||
+ {
|
||||
+ if (produced == 0 && inleft == inleft_before)
|
||||
+ {
|
||||
+ /* Output buffer too small to make progress. This is
|
||||
+ expected for very small output buffer sizes. */
|
||||
+ TEST_VERIFY_EXIT (outbufsize < 3);
|
||||
+ break;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (ret == (size_t) -1)
|
||||
+ FAIL_EXIT1 ("%s (outbufsize %zu): iconv: %m", encoding, outbufsize);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Flush any pending state (e.g. a buffered combined character).
|
||||
+ With outbufsize < 3, we could not store the first character, so
|
||||
+ the second character did not become pending, and there is nothing
|
||||
+ to flush. */
|
||||
+ {
|
||||
+ char *outptr = outbuf;
|
||||
+ size_t outleft = outbufsize;
|
||||
+
|
||||
+ size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ size_t produced = outptr - outbuf;
|
||||
+ alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
|
||||
+
|
||||
+ /* Second flush does not provide more data. */
|
||||
+ outptr = outbuf;
|
||||
+ outleft = outbufsize;
|
||||
+ ret = iconv (cd, NULL, NULL, &outptr, &outleft);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ TEST_VERIFY (outptr == outbuf);
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (!alloc_buffer_has_failed (&result_buf));
|
||||
+ size_t result_used
|
||||
+ = sizeof (result_storage) - alloc_buffer_size (&result_buf);
|
||||
+
|
||||
+ if (outbufsize >= 3)
|
||||
+ {
|
||||
+ TEST_COMPARE (inleft, 0);
|
||||
+ TEST_COMPARE (result_used, sizeof (expected) - shift);
|
||||
+ TEST_COMPARE_BLOB (result_storage, result_used,
|
||||
+ &expected[shift], sizeof (expected) - shift);
|
||||
+ }
|
||||
+ else
|
||||
+ /* If the buffer is too small, only the leading X could be converted. */
|
||||
+ TEST_COMPARE (result_used, 8 - shift);
|
||||
+
|
||||
+ TEST_VERIFY_EXIT (iconv_close (cd) == 0);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct support_next_to_fault ntf
|
||||
+ = support_next_to_fault_allocate (8);
|
||||
+
|
||||
+ for (int shift = 0; shift <= 8; ++shift)
|
||||
+ for (int truncate = 0; truncate < 2; ++truncate)
|
||||
+ for (size_t outbufsize = 1; outbufsize <= 8; outbufsize++)
|
||||
+ {
|
||||
+ char *outbuf = ntf.buffer + ntf.length - outbufsize;
|
||||
+ test_one ("IBM1390", shift, truncate, outbuf, outbufsize);
|
||||
+ test_one ("IBM1399", shift, truncate, outbuf, outbufsize);
|
||||
+ }
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
181
SOURCES/glibc-RHEL-168095.patch
Normal file
181
SOURCES/glibc-RHEL-168095.patch
Normal file
@ -0,0 +1,181 @@
|
||||
commit d8997716a1ca22cf038eac86ed286830ba9818cc
|
||||
Author: DJ Delorie <dj@redhat.com>
|
||||
Date: Wed Apr 1 17:52:25 2026 -0400
|
||||
|
||||
nss: fix __get_default_domain logic
|
||||
|
||||
Fix logic bug in __nss_get_default_domain that prevents
|
||||
proper initialization.
|
||||
|
||||
Because this function is not exposed, the test case must link
|
||||
against the object directly.
|
||||
|
||||
Bug origin commit: 64d1e08ea822bf47cb2796ad0f727136227f983c
|
||||
|
||||
Co-authored-by: Florian Weimer <fweimer@redhat.com>
|
||||
Reviewed-by: Frédéric Bérat <fberat@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
nss/Makefile
|
||||
(fixup context)
|
||||
|
||||
diff --git a/nss/Makefile b/nss/Makefile
|
||||
index 05fcadf60fd0d771..da0f0fdc0f70ff69 100644
|
||||
--- a/nss/Makefile
|
||||
+++ b/nss/Makefile
|
||||
@@ -55,6 +55,7 @@ extra-objs += $(makedb-modules:=.o)
|
||||
tests-static = tst-field
|
||||
tests-internal = tst-field
|
||||
tests = test-netdb test-digits-dots tst-nss-getpwent bug17079 \
|
||||
+ tst-default-domain \
|
||||
tst-nss-test1 \
|
||||
tst-nss-test2 \
|
||||
tst-nss-test3 \
|
||||
@@ -212,3 +213,5 @@ $(objpfx)tst-nss-files-hosts-multi: $(libdl)
|
||||
$(objpfx)tst-nss-files-hosts-getent: $(libdl)
|
||||
$(objpfx)tst-nss-files-alias-leak: $(libdl)
|
||||
$(objpfx)tst-nss-files-alias-leak.out: $(objpfx)libnss_files.so
|
||||
+
|
||||
+$(objpfx)tst-default-domain: $(objpfx)nisdomain.os
|
||||
diff --git a/nss/nss_compat/nisdomain.c b/nss/nss_compat/nisdomain.c
|
||||
index facce925b36d9418..def681af8f2363fb 100644
|
||||
--- a/nss/nss_compat/nisdomain.c
|
||||
+++ b/nss/nss_compat/nisdomain.c
|
||||
@@ -36,7 +36,7 @@ __nss_get_default_domain (char **outdomain)
|
||||
|
||||
__libc_lock_lock (domainname_lock);
|
||||
|
||||
- if (domainname[0] != '\0')
|
||||
+ if (domainname[0] == '\0')
|
||||
{
|
||||
if (getdomainname (domainname, MAXDOMAINNAMELEN) < 0)
|
||||
result = errno;
|
||||
diff --git a/nss/tst-default-domain.c b/nss/tst-default-domain.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..2fa9153d8802d4c3
|
||||
--- /dev/null
|
||||
+++ b/nss/tst-default-domain.c
|
||||
@@ -0,0 +1,123 @@
|
||||
+/* Basic test of __nss_get_default_domain
|
||||
+ Copyright (C) 2026 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <unistd.h>
|
||||
+#include <string.h>
|
||||
+#include <dlfcn.h>
|
||||
+
|
||||
+#include "nss_compat/nisdomain.h"
|
||||
+
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+char unset_domain[] = "unset_domain";
|
||||
+char new_domain[] = "new_domain";
|
||||
+
|
||||
+/* This function checks the __nss_get_default_domain() function in
|
||||
+ nss_compat/nssdomain.c. Because this is an internal function to
|
||||
+ libnss_compat.so, the Makefile will link that object to this test
|
||||
+ case directly. */
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *domain_name;
|
||||
+ char buf[1024];
|
||||
+
|
||||
+ /* We need to be in a network namespace so we can change the domain
|
||||
+ name without interfering with the host system. */
|
||||
+ support_become_root ();
|
||||
+ support_enter_network_namespace ();
|
||||
+ if (!support_in_uts_namespace ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ /* First pass: set an empty domain and make sure it's returned
|
||||
+ correctly. This should not be cached. */
|
||||
+
|
||||
+ /* Set the domain name to a known value. */
|
||||
+ TEST_VERIFY (setdomainname ("", 0) == 0);
|
||||
+
|
||||
+ /* Make sure it got set. */
|
||||
+ TEST_VERIFY (getdomainname (buf, sizeof(buf)) == 0);
|
||||
+ TEST_COMPARE_STRING (buf, "");
|
||||
+
|
||||
+ /* Set this to a known "unknown" value so we can detect if it's not
|
||||
+ changed. */
|
||||
+ domain_name = unset_domain;
|
||||
+
|
||||
+ /* This is the function we're testing. */
|
||||
+ TEST_VERIFY (__nss_get_default_domain (& domain_name) == 0);
|
||||
+
|
||||
+ /* Make sure the correct domain name is returned. */
|
||||
+ TEST_VERIFY (domain_name != NULL);
|
||||
+ TEST_COMPARE_STRING (domain_name, "");
|
||||
+
|
||||
+ /* Second pass: set a non-empty domain and make sure it's returned
|
||||
+ correctly. This works because the empty domain is not
|
||||
+ cached. */
|
||||
+
|
||||
+ /* Set the domain name to a known value. */
|
||||
+ TEST_VERIFY (setdomainname (new_domain, strlen (new_domain)) == 0);
|
||||
+
|
||||
+ /* Make sure it got set. */
|
||||
+ TEST_VERIFY (getdomainname (buf, sizeof(buf)) == 0);
|
||||
+ TEST_COMPARE_STRING (buf, new_domain);
|
||||
+
|
||||
+ /* Set this to a known "unknown" value so we can detect if it's not
|
||||
+ changed. */
|
||||
+ domain_name = unset_domain;
|
||||
+
|
||||
+ /* This is the function we're testing. */
|
||||
+ TEST_VERIFY (__nss_get_default_domain (& domain_name) == 0);
|
||||
+
|
||||
+ /* Make sure the correct domain name is returned. */
|
||||
+ TEST_VERIFY (domain_name != NULL);
|
||||
+ TEST_COMPARE_STRING (domain_name, new_domain);
|
||||
+
|
||||
+ /* The function caches the name, so check it twice. */
|
||||
+ TEST_VERIFY (__nss_get_default_domain (& domain_name) == 0);
|
||||
+
|
||||
+ TEST_VERIFY (domain_name != NULL);
|
||||
+ TEST_COMPARE_STRING (domain_name, new_domain);
|
||||
+
|
||||
+ /* Third pass: set an empty domain again but expect the cached
|
||||
+ value. */
|
||||
+
|
||||
+ /* Set the domain name to a known value. */
|
||||
+ TEST_VERIFY (setdomainname ("", 0) == 0);
|
||||
+
|
||||
+ /* Make sure it got set. */
|
||||
+ TEST_VERIFY (getdomainname (buf, sizeof(buf)) == 0);
|
||||
+ TEST_COMPARE_STRING (buf, "");
|
||||
+
|
||||
+ /* Set this to a known "unknown" value so we can detect if it's not
|
||||
+ changed. */
|
||||
+ domain_name = unset_domain;
|
||||
+
|
||||
+ /* This is the function we're testing. */
|
||||
+ TEST_VERIFY (__nss_get_default_domain (& domain_name) == 0);
|
||||
+
|
||||
+ TEST_VERIFY (domain_name != NULL);
|
||||
+ TEST_COMPARE_STRING (domain_name, new_domain);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
224
SOURCES/glibc-RHEL-173358-1.patch
Normal file
224
SOURCES/glibc-RHEL-173358-1.patch
Normal file
@ -0,0 +1,224 @@
|
||||
Test-only backport of test for CVE-2026-4437 that does not affect
|
||||
glibc-2.28. Test extracted from the following upstream commit:
|
||||
|
||||
commit 5663ab0b833df187b15e7bb4b18173e22beb8bd1
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Fri Mar 20 16:43:33 2026 -0400
|
||||
|
||||
resolv: Count records correctly (CVE-2026-4437)
|
||||
|
||||
The answer section boundary was previously ignored, and the code in
|
||||
getanswer_ptr would iterate past the last resource record, but not
|
||||
beyond the end of the returned data. This could lead to subsequent data
|
||||
being interpreted as answer records, thus violating the DNS
|
||||
specification. Such resource records could be maliciously crafted and
|
||||
hidden from other tooling, but processed by the glibc stub resolver and
|
||||
acted upon by the application. While we trust the data returned by the
|
||||
configured recursive resolvers, we should not trust its format and
|
||||
should validate it as required. It is a security issue to incorrectly
|
||||
process the DNS protocol.
|
||||
|
||||
A regression test is added for response section crossing.
|
||||
|
||||
No regressions on x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: Collin Funk <collin.funk1@gmail.com>
|
||||
(cherry picked from commit 9f5f18aab40ec6b61fa49a007615e6077e9a979b)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index f3feaf072a3ec66d..9837a8cfa145e1da 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -55,6 +55,7 @@ tests += \
|
||||
tst-res_use_inet6 \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-binary \
|
||||
+ tst-resolv-dns-section \
|
||||
tst-resolv-edns \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
@@ -65,6 +66,7 @@ tests += \
|
||||
tst-resolv-semi-failure \
|
||||
tst-resolv-short-response \
|
||||
tst-resolv-trailing \
|
||||
+ # tests
|
||||
|
||||
# This test calls __res_context_send directly, which is not exported
|
||||
# from libresolv.
|
||||
@@ -197,6 +199,8 @@ $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
|
||||
$(gen-locales) $(objpfx)tst-no-libidn2.so
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-dns-section: $(objpfx)libresolv.so \
|
||||
+ $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
|
||||
diff --git a/resolv/tst-resolv-dns-section.c b/resolv/tst-resolv-dns-section.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1171baef51e3cc36
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-dns-section.c
|
||||
@@ -0,0 +1,162 @@
|
||||
+/* Test handling of invalid section transitions (bug 34014).
|
||||
+ Copyright (C) 2022-2026 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
+#include <resolv.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/format_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+/* Name of test, and the second section type. */
|
||||
+struct item {
|
||||
+ const char *test;
|
||||
+ int ns_section;
|
||||
+};
|
||||
+
|
||||
+static const struct item test_items[] =
|
||||
+ {
|
||||
+ { "Test crossing from ns_s_an to ns_s_ar.", ns_s_ar },
|
||||
+ { "Test crossing from ns_s_an to ns_s_an.", ns_s_ns },
|
||||
+
|
||||
+ { NULL, 0 },
|
||||
+ };
|
||||
+
|
||||
+/* The response is designed to contain the following:
|
||||
+ - An Answer section with one T_PTR record that is skipped.
|
||||
+ - A second section with a semantically invalid T_PTR record.
|
||||
+ The original defect is that the response parsing would cross
|
||||
+ section boundaries and handle the additional section T_PTR
|
||||
+ as if it were an answer. A conforming implementation would
|
||||
+ stop as soon as it reaches the end of the section. */
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+
|
||||
+ /* We only test PTR. */
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int count;
|
||||
+ char *tail = NULL;
|
||||
+
|
||||
+ if (strstr (qname, "in-addr.arpa") != NULL
|
||||
+ && sscanf (qname, "%u.%ms", &count, &tail) == 2)
|
||||
+ TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
|
||||
+ else if (sscanf (qname, "%x.%ms", &count, &tail) == 2)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ /* We have a bounded number of possible tests. */
|
||||
+ TEST_VERIFY (count >= 0);
|
||||
+ TEST_VERIFY (count <= 15);
|
||||
+
|
||||
+ struct resolv_response_flags flags = {};
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+
|
||||
+ /* Actual answer record, but the wrong name (skipped). */
|
||||
+ resolv_response_open_record (b, "1.0.0.10.in-addr.arpa", qclass, qtype, 60);
|
||||
+
|
||||
+ /* Record the answer. */
|
||||
+ resolv_response_add_name (b, "test.ptr.example.net");
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ /* Add a second section to test section boundary crossing. */
|
||||
+ resolv_response_section (b, test_items[count].ns_section);
|
||||
+ /* Semantically incorrect, but hide a T_PTR entry. */
|
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
|
||||
+ resolv_response_add_name (b, "wrong.ptr.example.net");
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/* Perform one check using a reverse lookup. */
|
||||
+static void
|
||||
+check_reverse (int af, int count)
|
||||
+{
|
||||
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
|
||||
+ TEST_VERIFY (count < array_length (test_items));
|
||||
+
|
||||
+ char addr[sizeof (struct in6_addr)] = { 0 };
|
||||
+ socklen_t addrlen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ addr[0] = (char) 192;
|
||||
+ addr[1] = (char) 168;
|
||||
+ addr[2] = (char) 0;
|
||||
+ addr[3] = (char) count;
|
||||
+ addrlen = 4;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ addr[0] = 0x20;
|
||||
+ addr[1] = 0x01;
|
||||
+ addr[2] = 0x0d;
|
||||
+ addr[3] = 0xb8;
|
||||
+ addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
|
||||
+ addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
|
||||
+ addr[12] = 0x0;
|
||||
+ addr[13] = 0x0;
|
||||
+ addr[14] = 0x0;
|
||||
+ addr[15] = count;
|
||||
+ addrlen = 16;
|
||||
+ }
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ struct hostent *answer = gethostbyaddr (addr, addrlen, af);
|
||||
+ TEST_VERIFY (answer == NULL);
|
||||
+ TEST_VERIFY (h_errno == NO_RECOVERY);
|
||||
+ if (answer != NULL)
|
||||
+ printf ("error: unexpected success: %s\n",
|
||||
+ support_format_hostent (answer));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int i = 0; test_items[i].test != NULL; i++)
|
||||
+ {
|
||||
+ check_reverse (AF_INET, i);
|
||||
+ check_reverse (AF_INET6, i);
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
304
SOURCES/glibc-RHEL-173358-2.patch
Normal file
304
SOURCES/glibc-RHEL-173358-2.patch
Normal file
@ -0,0 +1,304 @@
|
||||
Test-only backport of test for CVE-2026-4438 that does not affect
|
||||
glibc-2.28. Test extracted from the following upstream commit:
|
||||
|
||||
commit 9344c796f7a4ac8f2c59de63f3e1e936b51e817d
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Fri Mar 20 17:14:33 2026 -0400
|
||||
|
||||
resolv: Check hostname for validity (CVE-2026-4438)
|
||||
|
||||
The processed hostname in getanswer_ptr should be correctly checked to
|
||||
avoid invalid characters from being allowed, including shell
|
||||
metacharacters. It is a security issue to fail to check the returned
|
||||
hostname for validity.
|
||||
|
||||
A regression test is added for invalid metacharacters and other cases
|
||||
of invalid or valid characters.
|
||||
|
||||
No regressions on x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
(cherry picked from commit e10977481f4db4b2a3ce34fa4c3a1e26651ae312)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 9837a8cfa145e1da..359e8a0a9b22aff9 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -57,6 +57,7 @@ tests += \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-dns-section \
|
||||
tst-resolv-edns \
|
||||
+ tst-resolv-invalid-ptr \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
tst-resolv-noaaaa-vc \
|
||||
@@ -208,6 +209,8 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-invalid-ptr: $(objpfx)libresolv.so \
|
||||
+ $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/tst-resolv-invalid-ptr.c b/resolv/tst-resolv-invalid-ptr.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0c802ab96780efb0
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-invalid-ptr.c
|
||||
@@ -0,0 +1,255 @@
|
||||
+/* Test handling of invalid T_PTR results (bug 34015).
|
||||
+ Copyright (C) 2022-2026 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
+#include <resolv.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/format_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+/* Name of test, the answer, the expected error return, and if we
|
||||
+ expect the call to fail. */
|
||||
+struct item {
|
||||
+ const char *test;
|
||||
+ const char *answer;
|
||||
+ int expected;
|
||||
+ bool fail;
|
||||
+};
|
||||
+
|
||||
+static const struct item test_items[] =
|
||||
+ {
|
||||
+ /* Test for invalid characters. */
|
||||
+ { "Invalid use of \"|\"",
|
||||
+ "test.|.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"&\"",
|
||||
+ "test.&.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \";\"",
|
||||
+ "test.;.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"<\"",
|
||||
+ "test.<.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \">\"",
|
||||
+ "test.>.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"(\"",
|
||||
+ "test.(.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \")\"",
|
||||
+ "test.).ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"$\"",
|
||||
+ "test.$.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"`\"",
|
||||
+ "test.`.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\\\"",
|
||||
+ "test.\\.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\'\"",
|
||||
+ "test.'.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\"\"",
|
||||
+ "test.\".ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \" \"",
|
||||
+ "test. .ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\\t\"",
|
||||
+ "test.\t.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\\n\"",
|
||||
+ "test.\n.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"\\r\"",
|
||||
+ "test.\r.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"*\"",
|
||||
+ "test.*.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"?\"",
|
||||
+ "test.?.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"[\"",
|
||||
+ "test.[.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"]\"",
|
||||
+ "test.].ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \",\"",
|
||||
+ "test.,.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"~\"",
|
||||
+ "test.~.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \":\"",
|
||||
+ "test.:.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"!\"",
|
||||
+ "test.!.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"@\"",
|
||||
+ "test.@.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"#\"",
|
||||
+ "test.#.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"%\"",
|
||||
+ "test.%%.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of \"^\"",
|
||||
+ "test.^.ptr.example", NO_RECOVERY, true },
|
||||
+
|
||||
+ /* Test for invalid UTF-8 characters (2-byte, 4-byte, 6-byte). */
|
||||
+ { "Invalid use of UTF-8 (2-byte, U+00C0-U+00C2)",
|
||||
+ "ÁÂÃ.test.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of UTF-8 (4-byte, U+0750-U+0752)",
|
||||
+ "ݐݑݒ.test.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Invalid use of UTF-8 (6-byte, U+0904-U+0906)",
|
||||
+ "ऄअआ.test.ptr.example", NO_RECOVERY, true },
|
||||
+
|
||||
+ /* Test for "-" which may be valid depending on position. */
|
||||
+ { "Invalid leading \"-\"",
|
||||
+ "-test.ptr.example", NO_RECOVERY, true },
|
||||
+ { "Valid trailing \"-\"",
|
||||
+ "test-.ptr.example", 0, false },
|
||||
+ { "Valid mid-label use of \"-\"",
|
||||
+ "te-st.ptr.example", 0, false },
|
||||
+
|
||||
+ /* Test for "_" which is always valid in any position. */
|
||||
+ { "Valid leading use of \"_\"",
|
||||
+ "_test.ptr.example", 0, false },
|
||||
+ { "Valid mid-label use of \"_\"",
|
||||
+ "te_st.ptr.example", 0, false },
|
||||
+ { "Valid trailing use of \"_\"",
|
||||
+ "test_.ptr.example", 0, false },
|
||||
+
|
||||
+ /* Sanity test the broader set [A-Za-z0-9_-] of valid characters. */
|
||||
+ { "Valid \"[A-Z]\"",
|
||||
+ "test.ABCDEFGHIJKLMNOPQRSTUVWXYZ.ptr.example", 0, false },
|
||||
+ { "Valid \"[a-z]\"",
|
||||
+ "test.abcdefghijklmnopqrstuvwxyz.ptr.example", 0, false },
|
||||
+ { "Valid \"[0-9]\"",
|
||||
+ "test.0123456789.ptr.example", 0, false },
|
||||
+ { "Valid mixed use of \"[A-Za-z0-9_-]\"",
|
||||
+ "test.012abcABZ_-.ptr.example", 0, false },
|
||||
+ };
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+
|
||||
+ /* We only test PTR. */
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int count, count1;
|
||||
+ char *tail = NULL;
|
||||
+
|
||||
+ /* The test implementation can handle up to 255 tests. */
|
||||
+ if (strstr (qname, "in-addr.arpa") != NULL
|
||||
+ && sscanf (qname, "%u.%ms", &count, &tail) == 2)
|
||||
+ TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
|
||||
+ else if (sscanf (qname, "%x.%x.%ms", &count, &count1, &tail) == 3)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ count |= count1 << 4;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ /* Cross check. Count has a fixed bound (soft limit). */
|
||||
+ TEST_VERIFY (count >= 0 && count <= 255);
|
||||
+
|
||||
+ /* We have a fixed number of tests (hard limit). */
|
||||
+ TEST_VERIFY_EXIT (count < array_length (test_items));
|
||||
+
|
||||
+ struct resolv_response_flags flags = {};
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+
|
||||
+ /* Actual answer record. */
|
||||
+ resolv_response_open_record (b, qname, qclass, qtype, 60);
|
||||
+
|
||||
+ /* Record the answer. */
|
||||
+ resolv_response_add_name (b, test_items[count].answer);
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
||||
+
|
||||
+/* Perform one check using a reverse lookup. */
|
||||
+static void
|
||||
+check_reverse (int af, int count)
|
||||
+{
|
||||
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
|
||||
+ TEST_VERIFY_EXIT (count < array_length (test_items));
|
||||
+
|
||||
+ /* Generate an address to query for each test. */
|
||||
+ char addr[sizeof (struct in6_addr)] = { 0 };
|
||||
+ socklen_t addrlen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ addr[0] = (char) 192;
|
||||
+ addr[1] = (char) 168;
|
||||
+ addr[2] = (char) 0;
|
||||
+ addr[3] = (char) count;
|
||||
+ addrlen = 4;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ addr[0] = 0x20;
|
||||
+ addr[1] = 0x01;
|
||||
+ addr[2] = 0x0d;
|
||||
+ addr[3] = 0xb8;
|
||||
+ addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
|
||||
+ addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
|
||||
+ addr[12] = 0x0;
|
||||
+ addr[13] = 0x0;
|
||||
+ addr[14] = 0x0;
|
||||
+ addr[15] = (char) count;
|
||||
+ addrlen = 16;
|
||||
+ }
|
||||
+
|
||||
+ h_errno = 0;
|
||||
+ struct hostent *answer = gethostbyaddr (addr, addrlen, af);
|
||||
+
|
||||
+ /* Verify h_errno is as expected. */
|
||||
+ TEST_COMPARE (h_errno, test_items[count].expected);
|
||||
+ if (h_errno != test_items[count].expected)
|
||||
+ /* And print more information if it's not. */
|
||||
+ printf ("INFO: %s\n", test_items[count].test);
|
||||
+
|
||||
+ if (test_items[count].fail)
|
||||
+ {
|
||||
+ /* We expected a failure so verify answer is NULL. */
|
||||
+ TEST_VERIFY (answer == NULL);
|
||||
+ /* If it's not NULL we should print out what we received. */
|
||||
+ if (answer != NULL)
|
||||
+ printf ("error: unexpected success: %s\n",
|
||||
+ support_format_hostent (answer));
|
||||
+ }
|
||||
+ else
|
||||
+ /* We don't expect a failure so answer must be valid. */
|
||||
+ TEST_COMPARE_STRING (answer->h_name, test_items[count].answer);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int i = 0; i < array_length (test_items); i++)
|
||||
+ {
|
||||
+ check_reverse (AF_INET, i);
|
||||
+ check_reverse (AF_INET6, i);
|
||||
+ }
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
@ -115,7 +115,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: %{glibcrelease}.34
|
||||
Release: %{glibcrelease}.37
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -1323,6 +1323,13 @@ Patch1088: glibc-RHEL-24169-21.patch
|
||||
Patch1089: glibc-RHEL-24169-22.patch
|
||||
Patch1090: glibc-RHEL-137185.patch
|
||||
Patch1091: glibc-RHEL-140104.patch
|
||||
Patch1092: glibc-RHEL-162891-1.patch
|
||||
Patch1093: glibc-RHEL-162891-2.patch
|
||||
Patch1094: glibc-RHEL-162891-3.patch
|
||||
Patch1095: glibc-RHEL-162891-4.patch
|
||||
Patch1096: glibc-RHEL-168095.patch
|
||||
Patch1097: glibc-RHEL-173358-1.patch
|
||||
Patch1098: glibc-RHEL-173358-2.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -2984,6 +2991,17 @@ fi
|
||||
%{_libdir}/libpthread_nonshared.a
|
||||
|
||||
%changelog
|
||||
* Mon May 11 2026 Arjun Shankar <arjun@redhat.com> - 2.28-251.37
|
||||
- Add tests for CVE-2026-4437 and CVE-2026-4438 (RHEL-173358)
|
||||
|
||||
* Mon May 11 2026 Frédéric Bérat <fberat@redhat.com> - 2.28-251.36
|
||||
- Fix __nss_get_default_domain logic to restore netgroup user enumeration
|
||||
(RHEL-168095)
|
||||
|
||||
* Mon May 04 2026 Frédéric Bérat <fberat@redhat.com> - 2.28-251.35
|
||||
- CVE-2026-4046: Fix assertion failure in IBM1390 and IBM1399 iconv modules
|
||||
(RHEL-162891)
|
||||
|
||||
* Wed Apr 15 2026 Patsy Griffin <patsy@redhat.com> - 2.28-251.34
|
||||
- Update locales for Croatia to use EUR as currency symbol. (RHEL-140104)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user