changeset 40213:cc3fed3b7788

unilbrk/u*-possible-linebreaks: Fix undefined behaviour. Reported by Jeffrey Walton <noloader@gmail.com>. * lib/unilbrk/u8-possible-linebreaks.c (u8_possible_linebreaks): Don't invoke memset with a zero size. * lib/unilbrk/u16-possible-linebreaks.c (u16_possible_linebreaks): Likewise. * lib/unilbrk/u32-possible-linebreaks.c (u32_possible_linebreaks): Adjust accordingly.
author Bruno Haible <bruno@clisp.org>
date Sat, 09 Mar 2019 00:27:19 +0100
parents 8da9577294da
children 452ab00796c7
files ChangeLog lib/unilbrk/u16-possible-linebreaks.c lib/unilbrk/u32-possible-linebreaks.c lib/unilbrk/u8-possible-linebreaks.c
diffstat 4 files changed, 353 insertions(+), 330 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sat Mar 09 00:01:47 2019 +0100
+++ b/ChangeLog	Sat Mar 09 00:27:19 2019 +0100
@@ -1,3 +1,14 @@
+2019-03-08  Bruno Haible  <bruno@clisp.org>
+
+	unilbrk/u*-possible-linebreaks: Fix undefined behaviour.
+	Reported by Jeffrey Walton <noloader@gmail.com>.
+	* lib/unilbrk/u8-possible-linebreaks.c (u8_possible_linebreaks): Don't
+	invoke memset with a zero size.
+	* lib/unilbrk/u16-possible-linebreaks.c (u16_possible_linebreaks):
+	Likewise.
+	* lib/unilbrk/u32-possible-linebreaks.c (u32_possible_linebreaks):
+	Adjust accordingly.
+
 2019-03-08  Bruno Haible  <bruno@clisp.org>
 
 	unistr/*, uniconv/*: Fix undefined behaviour.
--- a/lib/unilbrk/u16-possible-linebreaks.c	Sat Mar 09 00:01:47 2019 +0100
+++ b/lib/unilbrk/u16-possible-linebreaks.c	Sat Mar 09 00:27:19 2019 +0100
@@ -30,135 +30,139 @@
 void
 u16_possible_linebreaks (const uint16_t *s, size_t n, const char *encoding, char *p)
 {
-  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
-  const uint16_t *s_end = s + n;
-  int last_prop = LBP_BK; /* line break property of last non-space character */
-  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
-  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
-
-  /* Don't break inside multibyte characters.  */
-  memset (p, UC_BREAK_PROHIBITED, n);
-
-  while (s < s_end)
+  if (n > 0)
     {
-      ucs4_t uc;
-      int count = u16_mbtouc_unsafe (&uc, s, s_end - s);
-      int prop = unilbrkprop_lookup (uc);
+      int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+      const uint16_t *s_end = s + n;
+      int last_prop = LBP_BK; /* line break property of last non-space character */
+      char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+      char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
 
-      if (prop == LBP_BK)
+      /* Don't break inside multibyte characters.  */
+      memset (p, UC_BREAK_PROHIBITED, n);
+
+      do
         {
-          /* Mandatory break.  */
-          *p = UC_BREAK_MANDATORY;
-          last_prop = LBP_BK;
-          seen_space = NULL;
-          seen_space2 = NULL;
-        }
-      else
-        {
-          char *q;
+          ucs4_t uc;
+          int count = u16_mbtouc_unsafe (&uc, s, s_end - s);
+          int prop = unilbrkprop_lookup (uc);
 
-          /* Resolve property values whose behaviour is not fixed.  */
-          switch (prop)
+          if (prop == LBP_BK)
             {
-            case LBP_AI:
-              /* Resolve ambiguous.  */
-              prop = LBP_AI_REPLACEMENT;
-              break;
-            case LBP_CB:
-              /* This is arbitrary.  */
-              prop = LBP_ID;
-              break;
-            case LBP_SA:
-              /* We don't handle complex scripts yet.
-                 Treat LBP_SA like LBP_XX.  */
-            case LBP_XX:
-              /* This is arbitrary.  */
-              prop = LBP_AL;
-              break;
-            }
-
-          /* Deal with spaces and combining characters.  */
-          q = p;
-          if (prop == LBP_SP)
-            {
-              /* Don't break just before a space.  */
-              *p = UC_BREAK_PROHIBITED;
-              seen_space2 = seen_space;
-              seen_space = p;
-            }
-          else if (prop == LBP_ZW)
-            {
-              /* Don't break just before a zero-width space.  */
-              *p = UC_BREAK_PROHIBITED;
-              last_prop = LBP_ZW;
+              /* Mandatory break.  */
+              *p = UC_BREAK_MANDATORY;
+              last_prop = LBP_BK;
               seen_space = NULL;
               seen_space2 = NULL;
             }
-          else if (prop == LBP_CM)
+          else
             {
-              /* Don't break just before a combining character, except immediately after a
-                 zero-width space.  */
-              if (last_prop == LBP_ZW)
+              char *q;
+
+              /* Resolve property values whose behaviour is not fixed.  */
+              switch (prop)
+                {
+                case LBP_AI:
+                  /* Resolve ambiguous.  */
+                  prop = LBP_AI_REPLACEMENT;
+                  break;
+                case LBP_CB:
+                  /* This is arbitrary.  */
+                  prop = LBP_ID;
+                  break;
+                case LBP_SA:
+                  /* We don't handle complex scripts yet.
+                     Treat LBP_SA like LBP_XX.  */
+                case LBP_XX:
+                  /* This is arbitrary.  */
+                  prop = LBP_AL;
+                  break;
+                }
+
+              /* Deal with spaces and combining characters.  */
+              q = p;
+              if (prop == LBP_SP)
                 {
-                  /* Break after zero-width space.  */
-                  *p = UC_BREAK_POSSIBLE;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  last_prop = LBP_ID;
+                  /* Don't break just before a space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  seen_space2 = seen_space;
+                  seen_space = p;
+                }
+              else if (prop == LBP_ZW)
+                {
+                  /* Don't break just before a zero-width space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  last_prop = LBP_ZW;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
+                }
+              else if (prop == LBP_CM)
+                {
+                  /* Don't break just before a combining character, except immediately
+                     after a zero-width space.  */
+                  if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *p = UC_BREAK_POSSIBLE;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      last_prop = LBP_ID;
+                    }
+                  else
+                    {
+                      *p = UC_BREAK_PROHIBITED;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      if (seen_space != NULL)
+                        {
+                          q = seen_space;
+                          seen_space = seen_space2;
+                          prop = LBP_ID;
+                          goto lookup_via_table;
+                        }
+                    }
                 }
               else
                 {
-                  *p = UC_BREAK_PROHIBITED;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  if (seen_space != NULL)
+                 lookup_via_table:
+                  /* prop must be usable as an index for table 7.3 of UTR #14.  */
+                  if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
+                    abort ();
+
+                  if (last_prop == LBP_BK)
+                    {
+                      /* Don't break at the beginning of a line.  */
+                      *q = UC_BREAK_PROHIBITED;
+                    }
+                  else if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *q = UC_BREAK_POSSIBLE;
+                    }
+                  else
                     {
-                      q = seen_space;
-                      seen_space = seen_space2;
-                      prop = LBP_ID;
-                      goto lookup_via_table;
+                      switch (unilbrk_table [last_prop] [prop])
+                        {
+                        case D:
+                          *q = UC_BREAK_POSSIBLE;
+                          break;
+                        case I:
+                          *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                          break;
+                        case P:
+                          *q = UC_BREAK_PROHIBITED;
+                          break;
+                        default:
+                          abort ();
+                        }
                     }
+                  last_prop = prop;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
                 }
             }
-          else
-            {
-             lookup_via_table:
-              /* prop must be usable as an index for table 7.3 of UTR #14.  */
-              if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
-                abort ();
 
-              if (last_prop == LBP_BK)
-                {
-                  /* Don't break at the beginning of a line.  */
-                  *q = UC_BREAK_PROHIBITED;
-                }
-              else if (last_prop == LBP_ZW)
-                {
-                  /* Break after zero-width space.  */
-                  *q = UC_BREAK_POSSIBLE;
-                }
-              else
-                {
-                  switch (unilbrk_table [last_prop] [prop])
-                    {
-                    case D:
-                      *q = UC_BREAK_POSSIBLE;
-                      break;
-                    case I:
-                      *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
-                      break;
-                    case P:
-                      *q = UC_BREAK_PROHIBITED;
-                      break;
-                    default:
-                      abort ();
-                    }
-                }
-              last_prop = prop;
-              seen_space = NULL;
-              seen_space2 = NULL;
-            }
+          s += count;
+          p += count;
         }
-
-      s += count;
-      p += count;
+      while (s < s_end);
     }
 }
--- a/lib/unilbrk/u32-possible-linebreaks.c	Sat Mar 09 00:01:47 2019 +0100
+++ b/lib/unilbrk/u32-possible-linebreaks.c	Sat Mar 09 00:27:19 2019 +0100
@@ -28,131 +28,135 @@
 void
 u32_possible_linebreaks (const uint32_t *s, size_t n, const char *encoding, char *p)
 {
-  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
-  const uint32_t *s_end = s + n;
-  int last_prop = LBP_BK; /* line break property of last non-space character */
-  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
-  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
+  if (n > 0)
+    {
+      int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+      const uint32_t *s_end = s + n;
+      int last_prop = LBP_BK; /* line break property of last non-space character */
+      char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+      char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
 
-  while (s < s_end)
-    {
-      ucs4_t uc = *s;
-      int prop = unilbrkprop_lookup (uc);
-
-      if (prop == LBP_BK)
+      do
         {
-          /* Mandatory break.  */
-          *p = UC_BREAK_MANDATORY;
-          last_prop = LBP_BK;
-          seen_space = NULL;
-          seen_space2 = NULL;
-        }
-      else
-        {
-          char *q;
+          ucs4_t uc = *s;
+          int prop = unilbrkprop_lookup (uc);
 
-          /* Resolve property values whose behaviour is not fixed.  */
-          switch (prop)
+          if (prop == LBP_BK)
             {
-            case LBP_AI:
-              /* Resolve ambiguous.  */
-              prop = LBP_AI_REPLACEMENT;
-              break;
-            case LBP_CB:
-              /* This is arbitrary.  */
-              prop = LBP_ID;
-              break;
-            case LBP_SA:
-              /* We don't handle complex scripts yet.
-                 Treat LBP_SA like LBP_XX.  */
-            case LBP_XX:
-              /* This is arbitrary.  */
-              prop = LBP_AL;
-              break;
-            }
-
-          /* Deal with spaces and combining characters.  */
-          q = p;
-          if (prop == LBP_SP)
-            {
-              /* Don't break just before a space.  */
-              *p = UC_BREAK_PROHIBITED;
-              seen_space2 = seen_space;
-              seen_space = p;
-            }
-          else if (prop == LBP_ZW)
-            {
-              /* Don't break just before a zero-width space.  */
-              *p = UC_BREAK_PROHIBITED;
-              last_prop = LBP_ZW;
+              /* Mandatory break.  */
+              *p = UC_BREAK_MANDATORY;
+              last_prop = LBP_BK;
               seen_space = NULL;
               seen_space2 = NULL;
             }
-          else if (prop == LBP_CM)
+          else
             {
-              /* Don't break just before a combining character, except immediately after a
-                 zero-width space.  */
-              if (last_prop == LBP_ZW)
+              char *q;
+
+              /* Resolve property values whose behaviour is not fixed.  */
+              switch (prop)
+                {
+                case LBP_AI:
+                  /* Resolve ambiguous.  */
+                  prop = LBP_AI_REPLACEMENT;
+                  break;
+                case LBP_CB:
+                  /* This is arbitrary.  */
+                  prop = LBP_ID;
+                  break;
+                case LBP_SA:
+                  /* We don't handle complex scripts yet.
+                     Treat LBP_SA like LBP_XX.  */
+                case LBP_XX:
+                  /* This is arbitrary.  */
+                  prop = LBP_AL;
+                  break;
+                }
+
+              /* Deal with spaces and combining characters.  */
+              q = p;
+              if (prop == LBP_SP)
                 {
-                  /* Break after zero-width space.  */
-                  *p = UC_BREAK_POSSIBLE;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  last_prop = LBP_ID;
+                  /* Don't break just before a space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  seen_space2 = seen_space;
+                  seen_space = p;
+                }
+              else if (prop == LBP_ZW)
+                {
+                  /* Don't break just before a zero-width space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  last_prop = LBP_ZW;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
+                }
+              else if (prop == LBP_CM)
+                {
+                  /* Don't break just before a combining character, except immediately
+                     after a zero-width space.  */
+                  if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *p = UC_BREAK_POSSIBLE;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      last_prop = LBP_ID;
+                    }
+                  else
+                    {
+                      *p = UC_BREAK_PROHIBITED;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      if (seen_space != NULL)
+                        {
+                          q = seen_space;
+                          seen_space = seen_space2;
+                          prop = LBP_ID;
+                          goto lookup_via_table;
+                        }
+                    }
                 }
               else
                 {
-                  *p = UC_BREAK_PROHIBITED;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  if (seen_space != NULL)
+                 lookup_via_table:
+                  /* prop must be usable as an index for table 7.3 of UTR #14.  */
+                  if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
+                    abort ();
+
+                  if (last_prop == LBP_BK)
+                    {
+                      /* Don't break at the beginning of a line.  */
+                      *q = UC_BREAK_PROHIBITED;
+                    }
+                  else if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *q = UC_BREAK_POSSIBLE;
+                    }
+                  else
                     {
-                      q = seen_space;
-                      seen_space = seen_space2;
-                      prop = LBP_ID;
-                      goto lookup_via_table;
+                      switch (unilbrk_table [last_prop] [prop])
+                        {
+                        case D:
+                          *q = UC_BREAK_POSSIBLE;
+                          break;
+                        case I:
+                          *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                          break;
+                        case P:
+                          *q = UC_BREAK_PROHIBITED;
+                          break;
+                        default:
+                          abort ();
+                        }
                     }
+                  last_prop = prop;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
                 }
             }
-          else
-            {
-             lookup_via_table:
-              /* prop must be usable as an index for table 7.3 of UTR #14.  */
-              if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
-                abort ();
 
-              if (last_prop == LBP_BK)
-                {
-                  /* Don't break at the beginning of a line.  */
-                  *q = UC_BREAK_PROHIBITED;
-                }
-              else if (last_prop == LBP_ZW)
-                {
-                  /* Break after zero-width space.  */
-                  *q = UC_BREAK_POSSIBLE;
-                }
-              else
-                {
-                  switch (unilbrk_table [last_prop] [prop])
-                    {
-                    case D:
-                      *q = UC_BREAK_POSSIBLE;
-                      break;
-                    case I:
-                      *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
-                      break;
-                    case P:
-                      *q = UC_BREAK_PROHIBITED;
-                      break;
-                    default:
-                      abort ();
-                    }
-                }
-              last_prop = prop;
-              seen_space = NULL;
-              seen_space2 = NULL;
-            }
+          s++;
+          p++;
         }
-
-      s++;
-      p++;
+      while (s < s_end);
     }
 }
--- a/lib/unilbrk/u8-possible-linebreaks.c	Sat Mar 09 00:01:47 2019 +0100
+++ b/lib/unilbrk/u8-possible-linebreaks.c	Sat Mar 09 00:27:19 2019 +0100
@@ -30,136 +30,140 @@
 void
 u8_possible_linebreaks (const uint8_t *s, size_t n, const char *encoding, char *p)
 {
-  int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
-  const uint8_t *s_end = s + n;
-  int last_prop = LBP_BK; /* line break property of last non-space character */
-  char *seen_space = NULL; /* Was a space seen after the last non-space character? */
-  char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
-
-  /* Don't break inside multibyte characters.  */
-  memset (p, UC_BREAK_PROHIBITED, n);
-
-  while (s < s_end)
+  if (n > 0)
     {
-      ucs4_t uc;
-      int count = u8_mbtouc_unsafe (&uc, s, s_end - s);
-      int prop = unilbrkprop_lookup (uc);
+      int LBP_AI_REPLACEMENT = (is_cjk_encoding (encoding) ? LBP_ID : LBP_AL);
+      const uint8_t *s_end = s + n;
+      int last_prop = LBP_BK; /* line break property of last non-space character */
+      char *seen_space = NULL; /* Was a space seen after the last non-space character? */
+      char *seen_space2 = NULL; /* At least two spaces after the last non-space? */
 
-      if (prop == LBP_BK)
+      /* Don't break inside multibyte characters.  */
+      memset (p, UC_BREAK_PROHIBITED, n);
+
+      do
         {
-          /* Mandatory break.  */
-          *p = UC_BREAK_MANDATORY;
-          last_prop = LBP_BK;
-          seen_space = NULL;
-          seen_space2 = NULL;
-        }
-      else
-        {
-          char *q;
+          ucs4_t uc;
+          int count = u8_mbtouc_unsafe (&uc, s, s_end - s);
+          int prop = unilbrkprop_lookup (uc);
 
-          /* Resolve property values whose behaviour is not fixed.  */
-          switch (prop)
+          if (prop == LBP_BK)
             {
-            case LBP_AI:
-              /* Resolve ambiguous.  */
-              prop = LBP_AI_REPLACEMENT;
-              break;
-            case LBP_CB:
-              /* This is arbitrary.  */
-              prop = LBP_ID;
-              break;
-            case LBP_SA:
-              /* We don't handle complex scripts yet.
-                 Treat LBP_SA like LBP_XX.  */
-            case LBP_XX:
-              /* This is arbitrary.  */
-              prop = LBP_AL;
-              break;
-            }
-
-          /* Deal with spaces and combining characters.  */
-          q = p;
-          if (prop == LBP_SP)
-            {
-              /* Don't break just before a space.  */
-              *p = UC_BREAK_PROHIBITED;
-              seen_space2 = seen_space;
-              seen_space = p;
-            }
-          else if (prop == LBP_ZW)
-            {
-              /* Don't break just before a zero-width space.  */
-              *p = UC_BREAK_PROHIBITED;
-              last_prop = LBP_ZW;
+              /* Mandatory break.  */
+              *p = UC_BREAK_MANDATORY;
+              last_prop = LBP_BK;
               seen_space = NULL;
               seen_space2 = NULL;
             }
-          else if (prop == LBP_CM)
+          else
             {
-              /* Don't break just before a combining character, except immediately after a
-                 zero-width space.  */
-              if (last_prop == LBP_ZW)
+              char *q;
+
+              /* Resolve property values whose behaviour is not fixed.  */
+              switch (prop)
+                {
+                case LBP_AI:
+                  /* Resolve ambiguous.  */
+                  prop = LBP_AI_REPLACEMENT;
+                  break;
+                case LBP_CB:
+                  /* This is arbitrary.  */
+                  prop = LBP_ID;
+                  break;
+                case LBP_SA:
+                  /* We don't handle complex scripts yet.
+                     Treat LBP_SA like LBP_XX.  */
+                case LBP_XX:
+                  /* This is arbitrary.  */
+                  prop = LBP_AL;
+                  break;
+                }
+
+              /* Deal with spaces and combining characters.  */
+              q = p;
+              if (prop == LBP_SP)
                 {
-                  /* Break after zero-width space.  */
-                  *p = UC_BREAK_POSSIBLE;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  last_prop = LBP_ID;
+                  /* Don't break just before a space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  seen_space2 = seen_space;
+                  seen_space = p;
+                }
+              else if (prop == LBP_ZW)
+                {
+                  /* Don't break just before a zero-width space.  */
+                  *p = UC_BREAK_PROHIBITED;
+                  last_prop = LBP_ZW;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
+                }
+              else if (prop == LBP_CM)
+                {
+                  /* Don't break just before a combining character, except immediately
+                     after a zero-width space.  */
+                  if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *p = UC_BREAK_POSSIBLE;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      last_prop = LBP_ID;
+                    }
+                  else
+                    {
+                      *p = UC_BREAK_PROHIBITED;
+                      /* A combining character turns a preceding space into LBP_ID.  */
+                      if (seen_space != NULL)
+                        {
+                          q = seen_space;
+                          seen_space = seen_space2;
+                          prop = LBP_ID;
+                          goto lookup_via_table;
+                        }
+                    }
                 }
               else
                 {
-                  *p = UC_BREAK_PROHIBITED;
-                  /* A combining character turns a preceding space into LBP_ID.  */
-                  if (seen_space != NULL)
+                 lookup_via_table:
+                  /* prop must be usable as an index for table 7.3 of UTR #14.  */
+                  if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
+                    abort ();
+
+                  if (last_prop == LBP_BK)
+                    {
+                      /* Don't break at the beginning of a line.  */
+                      *q = UC_BREAK_PROHIBITED;
+                    }
+                  else if (last_prop == LBP_ZW)
+                    {
+                      /* Break after zero-width space.  */
+                      *q = UC_BREAK_POSSIBLE;
+                    }
+                  else
                     {
-                      q = seen_space;
-                      seen_space = seen_space2;
-                      prop = LBP_ID;
-                      goto lookup_via_table;
+                      switch (unilbrk_table [last_prop] [prop])
+                        {
+                        case D:
+                          *q = UC_BREAK_POSSIBLE;
+                          break;
+                        case I:
+                          *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
+                          break;
+                        case P:
+                          *q = UC_BREAK_PROHIBITED;
+                          break;
+                        default:
+                          abort ();
+                        }
                     }
+                  last_prop = prop;
+                  seen_space = NULL;
+                  seen_space2 = NULL;
                 }
             }
-          else
-            {
-             lookup_via_table:
-              /* prop must be usable as an index for table 7.3 of UTR #14.  */
-              if (!(prop >= 0 && prop < sizeof (unilbrk_table) / sizeof (unilbrk_table[0])))
-                abort ();
 
-              if (last_prop == LBP_BK)
-                {
-                  /* Don't break at the beginning of a line.  */
-                  *q = UC_BREAK_PROHIBITED;
-                }
-              else if (last_prop == LBP_ZW)
-                {
-                  /* Break after zero-width space.  */
-                  *q = UC_BREAK_POSSIBLE;
-                }
-              else
-                {
-                  switch (unilbrk_table [last_prop] [prop])
-                    {
-                    case D:
-                      *q = UC_BREAK_POSSIBLE;
-                      break;
-                    case I:
-                      *q = (seen_space != NULL ? UC_BREAK_POSSIBLE : UC_BREAK_PROHIBITED);
-                      break;
-                    case P:
-                      *q = UC_BREAK_PROHIBITED;
-                      break;
-                    default:
-                      abort ();
-                    }
-                }
-              last_prop = prop;
-              seen_space = NULL;
-              seen_space2 = NULL;
-            }
+          s += count;
+          p += count;
         }
-
-      s += count;
-      p += count;
+      while (s < s_end);
     }
 }