Dmitri A. Sergatskov wrote: > octave:1> s = char([72 101 108 108 111 44 32 228 189 160 229 165 189]); > octave:2> save -mat test.mat s > ../../libgnu/unistr/u8-to-u16.c:80:34: runtime error: applying zero offset > to null pointer > SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior > ../../libgnu/unistr/u8-to-u16.c:80:34
You can temporarily apply a workaround like the attached patch, through the gnulib-tool --local-dir option. [1] Bruno [1] https://www.gnu.org/software/gnulib/manual/html_node/Extending-Gnulib.html
diff --git a/lib/unistr/u16-to-u8.c b/lib/unistr/u16-to-u8.c index d9f092c48c..fe8b7228a1 100644 --- a/lib/unistr/u16-to-u8.c +++ b/lib/unistr/u16-to-u8.c @@ -36,10 +36,23 @@ #include <stdlib.h> #include <string.h> +/* END_OF_ARRAY(array,n) returns a pointer past the last element of the array + ARRAY that has N elements. + For clang, it uses a conditional expression that avoids adding 0 to a null + pointer, which is undefined according to ISO C 23 ?? 6.5.6.(9) and which + triggers an error in clang's undefined-behaviour sanitizer. When no + sanitizer is in effect, clang optimizes this conditional expression to + exactly the same code. */ +#if defined __clang__ +# define END_OF_ARRAY(array,n) ((n) ? (array) + (n) : (array)) +#else +# define END_OF_ARRAY(array,n) ((array) + (n)) +#endif + DST_UNIT * FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) { - const SRC_UNIT *s_end = s + n; + const SRC_UNIT *s_end = END_OF_ARRAY (s, n); /* Output string accumulator. */ DST_UNIT *result; size_t allocated; @@ -77,7 +90,7 @@ FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) s += count; /* Store it in the output string. */ - count = u8_uctomb (result + length, uc, allocated - length); + count = u8_uctomb (END_OF_ARRAY (result, length), uc, allocated - length); if (count == -1) { if (!(result == resultbuf || result == NULL)) @@ -109,7 +122,7 @@ FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) memcpy ((char *) memory, (char *) result, length * sizeof (DST_UNIT)); result = memory; - count = u8_uctomb (result + length, uc, allocated - length); + count = u8_uctomb (END_OF_ARRAY (result, length), uc, allocated - length); if (count < 0) abort (); } diff --git a/lib/unistr/u32-to-u8.c b/lib/unistr/u32-to-u8.c index 0c4f0bc3cc..9741058440 100644 --- a/lib/unistr/u32-to-u8.c +++ b/lib/unistr/u32-to-u8.c @@ -28,10 +28,23 @@ #include <stdlib.h> #include <string.h> +/* END_OF_ARRAY(array,n) returns a pointer past the last element of the array + ARRAY that has N elements. + For clang, it uses a conditional expression that avoids adding 0 to a null + pointer, which is undefined according to ISO C 23 ?? 6.5.6.(9) and which + triggers an error in clang's undefined-behaviour sanitizer. When no + sanitizer is in effect, clang optimizes this conditional expression to + exactly the same code. */ +#if defined __clang__ +# define END_OF_ARRAY(array,n) ((n) ? (array) + (n) : (array)) +#else +# define END_OF_ARRAY(array,n) ((array) + (n)) +#endif + DST_UNIT * FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) { - const SRC_UNIT *s_end = s + n; + const SRC_UNIT *s_end = END_OF_ARRAY (s, n); /* Output string accumulator. */ DST_UNIT *result; size_t allocated; @@ -63,7 +76,7 @@ FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) u8_uctomb will verify uc anyway. */ /* Store it in the output string. */ - count = u8_uctomb (result + length, uc, allocated - length); + count = u8_uctomb (END_OF_ARRAY (result, length), uc, allocated - length); if (count == -1) { if (!(result == resultbuf || result == NULL)) @@ -95,7 +108,7 @@ FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp) memcpy ((char *) memory, (char *) result, length * sizeof (DST_UNIT)); result = memory; - count = u8_uctomb (result + length, uc, allocated - length); + count = u8_uctomb (END_OF_ARRAY (result, length), uc, allocated - length); if (count < 0) abort (); }