Page MenuHome GnuPG

libgpg-error: String filter should *NOT* be called with non-nul-terminated string
Closed, ResolvedPublic

Description

In libgpg-error 1.33, formatting "%s", string filter is introduced.
But it may be "%.*s". In this case, string filter should not be called, because it may be non-nul-terminated string.
Otherwise, the process may get SEGV, in the call of filter accessing invalid memory scanning over allocated area.

(If we could be back in the day of 1.32, the filter function would have an argument for args->precision, though).

Event Timeline

gniibe created this task.
gniibe added a project: gpgrt.
gniibe updated the task description. (Show Details)
werner triaged this task as Normal priority.Sep 30 2023, 2:08 PM
werner added a subscriber: werner.

I guess we should add an extended API to set the filter.

gniibe changed the task status from Open to Testing.Dec 27 2023, 1:26 AM

We could also pass a nul terminated copy to the filter function in pr_string.

Like this:

@@ -1196,10 +1196,25 @@ pr_string (estream_printf_out_t outfnc, void *outfncarg,
    future, when breaking API/ABI is OK, we can change signature of
    gpgrt_string_filter_t to have another argument for precision.  */
   int allow_non_nul_string = (arg->precision >= 0);
+  char *stringbuf = NULL;
 
   if (arg->vt != VALTYPE_STRING)
     return -1;
-  if (sf && !allow_non_nul_string)
+
+  if (!value.a_string)
+    string = NULL;
+  else if (sf && allow_non_nul_string)
+    {
+      for (n=0,s=value.a_string; n < arg->precision && *s; s++)
+        n++;
+      stringbuf = malloc (n+1);
+      if (!stringbuf)
+        return -1;
+      memcpy (stringbuf, value.a_string, n);
+      stringbuf[n] = 0;
+      string = sf (stringbuf, string_no, sfvalue);
+    }
+  else if (sf)
     string = sf (value.a_string, string_no, sfvalue);
   else
     string = value.a_string;
@@ -1240,7 +1255,13 @@ pr_string (estream_printf_out_t outfnc, void *outfncarg,
   rc = 0;
 
  leave:
-  if (sf && !allow_non_nul_string) /* Tell the filter to release resources.  */
+  /* Tell the filter to release resources.  */
+  if (sf && stringbuf)
+    {
+      sf (stringbuf, -1, sfvalue);
+      free (stringbuf);
+    }
+  else if (sf)
     sf (value.a_string, -1, sfvalue);
 
   return rc;
werner changed the task status from Testing to Open.Jan 15 2024, 12:25 PM

I see your point: allocating STRINGBUF to make sure nul-terminated string.
The code itself doesn't work well in a test case of tests/t-prinntf.c, because it assumes string filter should be called with NULL for string.

To handle all the things, I'd revert the change of mine and then applying the idea of allocating STRINGBUF, keeping the behavior of limiting by arg->precision.

werner moved this task from QA to Done on the gpgrt board.