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 ();
         }

Reply via email to