Make state file parsing errors more explicit. Also don't leak the deltas.
authortb <tb@openbsd.org>
Tue, 3 Sep 2024 15:37:03 +0000 (15:37 +0000)
committertb <tb@openbsd.org>
Tue, 3 Sep 2024 15:37:03 +0000 (15:37 +0000)
joint effort with/ok claudio

usr.sbin/rpki-client/repo.c

index 064d8d0..9505686 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: repo.c,v 1.65 2024/09/03 13:31:31 claudio Exp $ */
+/*     $OpenBSD: repo.c,v 1.66 2024/09/03 15:37:03 tb Exp $ */
 /*
  * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
  * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -656,7 +656,7 @@ rrdp_session_parse(struct rrdprepo *rr)
 {
        FILE *f;
        struct rrdp_session *state;
-       int fd, ln = 0, deltacnt = 0;
+       int fd, i, ln = 0, deltacnt = 0;
        const char *errstr;
        char *line = NULL, *file;
        size_t len = 0;
@@ -691,13 +691,19 @@ rrdp_session_parse(struct rrdprepo *rr)
                        break;
                case 1:
                        state->serial = strtonum(line, 1, LLONG_MAX, &errstr);
-                       if (errstr)
-                               goto fail;
+                       if (errstr) {
+                               warnx("%s: state file: serial is %s: %s",
+                                  rr->basedir, errstr, line);
+                               goto reset;
+                       }
                        break;
                case 2:
                        rr->last_reset = strtonum(line, 1, LLONG_MAX, &errstr);
-                       if (errstr)
-                               goto fail;
+                       if (errstr) {
+                               warnx("%s: state file: last_reset is %s: %s",
+                                   rr->basedir, errstr, line);
+                               goto reset;
+                       }
                        break;
                case 3:
                        if (strcmp(line, "-") == 0)
@@ -706,8 +712,11 @@ rrdp_session_parse(struct rrdprepo *rr)
                                err(1, NULL);
                        break;
                default:
-                       if (deltacnt >= MAX_RRDP_DELTAS)
-                               goto fail;
+                       if (deltacnt >= MAX_RRDP_DELTAS) {
+                               warnx("%s: state file: too many deltas: %d",
+                                   rr->basedir, deltacnt);
+                               goto reset;
+                       }
                        if ((state->deltas[deltacnt++] = strdup(line)) == NULL)
                                err(1, NULL);
                        break;
@@ -715,6 +724,11 @@ rrdp_session_parse(struct rrdprepo *rr)
                ln++;
        }
 
+       if (ferror(f)) {
+               warn("%s: error reading state file", rr->basedir);
+               goto reset;
+       }
+
        /* check if it's time for reinitialization */
        weeks = (now - rr->last_reset) / (86400 * 7);
        if (now <= rr->last_reset || weeks > RRDP_RANDOM_REINIT_MAX) {
@@ -726,20 +740,17 @@ rrdp_session_parse(struct rrdprepo *rr)
                goto reset;
        }
 
-       if (ferror(f))
-               goto fail;
        fclose(f);
        free(line);
        return state;
 
- fail:
-       warnx("%s: corrupted state file, reinitializing", rr->basedir);
-
  reset:
        fclose(f);
        free(line);
        free(state->session_id);
        free(state->last_mod);
+       for (i = 0; i < MAX_RRDP_DELTAS; i++)
+               free(state->deltas[i]);
        memset(state, 0, sizeof(*state));
        rr->last_reset = now;
        return state;