Imported Upstream version 2.25.3
[platform/upstream/git.git] / gpg-interface.c
index 8ed2745..131e7d5 100644 (file)
@@ -105,6 +105,16 @@ static struct {
        { 0, "VALIDSIG ", GPG_STATUS_FINGERPRINT },
 };
 
+static void replace_cstring(char **field, const char *line, const char *next)
+{
+       free(*field);
+
+       if (line && next)
+               *field = xmemdupz(line, next - line);
+       else
+               *field = NULL;
+}
+
 static void parse_gpg_output(struct signature_check *sigc)
 {
        const char *buf = sigc->gpg_status;
@@ -116,6 +126,9 @@ static void parse_gpg_output(struct signature_check *sigc)
        for (line = buf; *line; line = strchrnul(line+1, '\n')) {
                while (*line == '\n')
                        line++;
+               if (!*line)
+                       break;
+
                /* Skip lines that don't start with GNUPG status */
                if (!skip_prefix(line, "[GNUPG:] ", &line))
                        continue;
@@ -133,33 +146,43 @@ static void parse_gpg_output(struct signature_check *sigc)
                                /* Do we have key information? */
                                if (sigcheck_gpg_status[i].flags & GPG_STATUS_KEYID) {
                                        next = strchrnul(line, ' ');
-                                       free(sigc->key);
-                                       sigc->key = xmemdupz(line, next - line);
+                                       replace_cstring(&sigc->key, line, next);
                                        /* Do we have signer information? */
                                        if (*next && (sigcheck_gpg_status[i].flags & GPG_STATUS_UID)) {
                                                line = next + 1;
                                                next = strchrnul(line, '\n');
-                                               free(sigc->signer);
-                                               sigc->signer = xmemdupz(line, next - line);
+                                               replace_cstring(&sigc->signer, line, next);
                                        }
                                }
                                /* Do we have fingerprint? */
                                if (sigcheck_gpg_status[i].flags & GPG_STATUS_FINGERPRINT) {
-                                       next = strchrnul(line, ' ');
-                                       free(sigc->fingerprint);
-                                       sigc->fingerprint = xmemdupz(line, next - line);
+                                       const char *limit;
+                                       char **field;
 
-                                       /* Skip interim fields */
+                                       next = strchrnul(line, ' ');
+                                       replace_cstring(&sigc->fingerprint, line, next);
+
+                                       /*
+                                        * Skip interim fields.  The search is
+                                        * limited to the same line since only
+                                        * OpenPGP signatures has a field with
+                                        * the primary fingerprint.
+                                        */
+                                       limit = strchrnul(line, '\n');
                                        for (j = 9; j > 0; j--) {
-                                               if (!*next)
+                                               if (!*next || limit <= next)
                                                        break;
                                                line = next + 1;
                                                next = strchrnul(line, ' ');
                                        }
 
-                                       next = strchrnul(line, '\n');
-                                       free(sigc->primary_key_fingerprint);
-                                       sigc->primary_key_fingerprint = xmemdupz(line, next - line);
+                                       field = &sigc->primary_key_fingerprint;
+                                       if (!j) {
+                                               next = strchrnul(line, '\n');
+                                               replace_cstring(field, line, next);
+                                       } else {
+                                               replace_cstring(field, NULL, NULL);
+                                       }
                                }
 
                                break;