- Backport: iconv: Remove public declaration of __gconv_transliterate - Backport: iconv: Remove _STRING_ARCH_unaligned usage for get/set macros - Backport: iconv: Remove _STRING_ARCH_unaligned usage - Backport: Use pending character state in IBM1390, IBM1399 character sets (CVE-2026-4046) Resolves: RHEL-162891
370 lines
13 KiB
Diff
370 lines
13 KiB
Diff
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; \
|
|
}
|
|
|