agent: Fix segv running in --server mode
[gnupg.git] / common / stringhelp.c
index dea2212..0abac8a 100644 (file)
@@ -6,8 +6,8 @@
  *
  * This file is part of GnuPG.
  *
- * GnuPG is free software; you can redistribute it and/or modify it
- * under the terms of either
+ * GnuPG is free software; you can redistribute and/or modify this
+ * part of GnuPG under the terms of either
  *
  *   - the GNU Lesser General Public License as published by the Free
  *     Software Foundation; either version 3 of the License, or (at
@@ -1052,7 +1052,8 @@ do_percent_escape (const char *str, const char *extra, int die)
     return NULL;
 
   for (i=j=0; str[i]; i++)
-    if (str[i] == ':' || str[i] == '%' || (extra && strchr (extra, str[i])))
+    if (str[i] == ':' || str[i] == '%' || str[i] == '\n'
+        || (extra && strchr (extra, str[i])))
       j++;
   if (die)
     ptr = xmalloc (i + 2 * j + 1);
@@ -1077,6 +1078,13 @@ do_percent_escape (const char *str, const char *extra, int die)
          ptr[i++] = '2';
          ptr[i++] = '5';
        }
+      else if (*str == '\n')
+       {
+         /* The newline is problematic in a line-based format.  */
+         ptr[i++] = '%';
+         ptr[i++] = '0';
+         ptr[i++] = 'a';
+       }
       else if (extra && strchr (extra, *str))
         {
          ptr[i++] = '%';
@@ -1331,6 +1339,42 @@ split_fields (char *string, char **array, int arraysize)
 }
 
 
+/* Split a string into colon delimited fields A pointer to each field
+ * is stored in ARRAY.  Stop splitting at ARRAYSIZE fields.  The
+ * function modifies STRING.  The number of parsed fields is returned.
+ * Note that leading and trailing spaces are not removed from the fields.
+ * Example:
+ *
+ *   char *fields[2];
+ *   if (split_fields (string, fields, DIM (fields)) < 2)
+ *     return  // Not enough args.
+ *   foo (fields[0]);
+ *   foo (fields[1]);
+ */
+int
+split_fields_colon (char *string, char **array, int arraysize)
+{
+  int n = 0;
+  char *p, *pend;
+
+  p = string;
+  do
+    {
+      if (n == arraysize)
+        break;
+      array[n++] = p;
+      pend = strchr (p, ':');
+      if (!pend)
+        break;
+      *pend++ = 0;
+      p = pend;
+    }
+  while (*p);
+
+  return n;
+}
+
+
 \f
 /* Version number parsing.  */
 
@@ -1435,13 +1479,13 @@ compare_version_strings (const char *my_version, const char *req_version)
 
 \f
 /* Format a string so that it fits within about TARGET_COLS columns.
-   If IN_PLACE is 0, then TEXT is copied to a new buffer, which is
-   returned.  Otherwise, TEXT is modified in place and returned.
  Normally, target_cols will be 72 and max_cols is 80.  */
+ * TEXT_IN is copied to a new buffer, which is returned.  Normally,
+ * target_cols will be 72 and max_cols is 80.  On error NULL is
* returned and ERRNO is set. */
 char *
-format_text (char *text, int in_place, int target_cols, int max_cols)
+format_text (const char *text_in, int target_cols, int max_cols)
 {
-  const int do_debug = 0;
+  /* const int do_debug = 0; */
 
   /* The character under consideration.  */
   char *p;
@@ -1451,9 +1495,11 @@ format_text (char *text, int in_place, int target_cols, int max_cols)
   char *last_space = NULL;
   int last_space_cols = 0;
   int copied_last_space = 0;
+  char *text;
 
-  if (! in_place)
-    text = xstrdup (text);
+  text = xtrystrdup (text_in);
+  if (!text)
+    return NULL;
 
   p = line = text;
   while (1)
@@ -1507,9 +1553,9 @@ format_text (char *text, int in_place, int target_cols, int max_cols)
           cols_with_left_space = last_space_cols;
           cols_with_right_space = cols;
 
-          if (do_debug)
-            log_debug ("Breaking: '%.*s'\n",
-                       (int) ((uintptr_t) p - (uintptr_t) line), line);
+          /* if (do_debug) */
+          /*   log_debug ("Breaking: '%.*s'\n", */
+          /*              (int) ((uintptr_t) p - (uintptr_t) line), line); */
 
           /* The number of columns away from TARGET_COLS.  We prefer
              to underflow than to overflow.  */
@@ -1521,21 +1567,22 @@ format_text (char *text, int in_place, int target_cols, int max_cols)
                max_cols.  */
             right_penalty += 4 * (cols_with_right_space - max_cols);
 
-          if (do_debug)
-            log_debug ("Left space => %d cols (penalty: %d); right space => %d cols (penalty: %d)\n",
-                       cols_with_left_space, left_penalty,
-                       cols_with_right_space, right_penalty);
+          /* if (do_debug) */
+          /*   log_debug ("Left space => %d cols (penalty: %d); " */
+          /*              "right space => %d cols (penalty: %d)\n", */
+          /*              cols_with_left_space, left_penalty, */
+          /*              cols_with_right_space, right_penalty); */
           if (last_space_cols && left_penalty <= right_penalty)
-            /* Prefer the left space.  */
             {
-              if (do_debug)
-                log_debug ("Breaking at left space.\n");
+              /* Prefer the left space.  */
+              /* if (do_debug) */
+              /*   log_debug ("Breaking at left space.\n"); */
               p = last_space;
             }
           else
             {
-              if (do_debug)
-                log_debug ("Breaking at right space.\n");
+              /* if (do_debug) */
+              /*   log_debug ("Breaking at right space.\n"); */
             }
 
           if (! *p)