summaryrefslogtreecommitdiff
path: root/src/libsystemd
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-05-07 00:19:24 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-05-07 00:28:19 +0900
commitfa1071819c2f6b1398543c0f9a41380a3fd52b30 (patch)
tree1be4ed944c2de9a4de7026c2d706786e96da7cf5 /src/libsystemd
parente562f131585fe6ae32b1f035ba48c1548d695259 (diff)
downloadsystemd-fa1071819c2f6b1398543c0f9a41380a3fd52b30.tar.gz
sd-journal: split out generic_array_bisect_one() from generic_array_bisect()
This also makes journal corruption always handled gracefully, and drop potentially unsatisfied assertion on corrupted journal. Fixes #27533.
Diffstat (limited to 'src/libsystemd')
-rw-r--r--src/libsystemd/sd-journal/journal-file.c154
1 files changed, 72 insertions, 82 deletions
diff --git a/src/libsystemd/sd-journal/journal-file.c b/src/libsystemd/sd-journal/journal-file.c
index f594b3eecb..78dc935161 100644
--- a/src/libsystemd/sd-journal/journal-file.c
+++ b/src/libsystemd/sd-journal/journal-file.c
@@ -2775,6 +2775,59 @@ enum {
TEST_RIGHT
};
+static int generic_array_bisect_one(
+ JournalFile *f,
+ uint64_t a, /* offset of entry array object. */
+ uint64_t i, /* index of the entry item we will test. */
+ uint64_t needle,
+ int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
+ direction_t direction,
+ uint64_t *left,
+ uint64_t *right,
+ uint64_t *ret_offset) {
+
+ Object *array;
+ uint64_t p;
+ int r;
+
+ assert(f);
+ assert(test_object);
+ assert(left);
+ assert(right);
+ assert(*left <= i);
+ assert(i <= *right);
+
+ r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
+ if (r < 0)
+ return r;
+
+ p = journal_file_entry_array_item(f, array, i);
+ if (p <= 0)
+ r = -EBADMSG;
+ else
+ r = test_object(f, p, needle);
+ if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
+ log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short.");
+ *right = i;
+ return -ENOANO; /* recognizable error */
+ }
+ if (r < 0)
+ return r;
+
+ if (r == TEST_FOUND)
+ r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
+
+ if (r == TEST_RIGHT)
+ *right = i;
+ else
+ *left = i + 1;
+
+ if (ret_offset)
+ *ret_offset = p;
+
+ return r;
+}
+
static int generic_array_bisect(
JournalFile *f,
uint64_t first,
@@ -2833,7 +2886,7 @@ static int generic_array_bisect(
}
while (a > 0) {
- uint64_t left, right, k, lp;
+ uint64_t left = 0, right, k, lp;
r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &array);
if (r < 0)
@@ -2844,76 +2897,30 @@ static int generic_array_bisect(
if (right <= 0)
return 0;
- i = right - 1;
- lp = p = journal_file_entry_array_item(f, array, i);
- if (p <= 0)
- r = -EBADMSG;
- else
- r = test_object(f, p, needle);
- if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
- log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (1)");
- n = i;
+ right--;
+ r = generic_array_bisect_one(f, a, right, needle, test_object, direction, &left, &right, &lp);
+ if (r == -ENOANO) {
+ n = right;
continue;
}
if (r < 0)
return r;
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
-
if (r == TEST_RIGHT) {
- left = 0;
- right -= 1;
-
- if (last_index != UINT64_MAX) {
- assert(last_index <= right);
-
- /* If we cached the last index we
- * looked at, let's try to not to jump
- * too wildly around and see if we can
- * limit the range to look at early to
- * the immediate neighbors of the last
- * index we looked at. */
-
- if (last_index > 0) {
- uint64_t x = last_index - 1;
-
- p = journal_file_entry_array_item(f, array, x);
- if (p <= 0)
- return -EBADMSG;
-
- r = test_object(f, p, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
+ /* If we cached the last index we looked at, let's try to not to jump too wildly
+ * around and see if we can limit the range to look at early to the immediate
+ * neighbors of the last index we looked at. */
- if (r == TEST_RIGHT)
- right = x;
- else
- left = x + 1;
- }
-
- if (last_index < right) {
- uint64_t y = last_index + 1;
-
- p = journal_file_entry_array_item(f, array, y);
- if (p <= 0)
- return -EBADMSG;
-
- r = test_object(f, p, needle);
- if (r < 0)
- return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
+ if (last_index > 0 && last_index - 1 < right) {
+ r = generic_array_bisect_one(f, a, last_index - 1, needle, test_object, direction, &left, &right, NULL);
+ if (r < 0 && r != -ENOANO)
+ return r;
+ }
- if (r == TEST_RIGHT)
- right = y;
- else
- left = y + 1;
- }
+ if (last_index < right) {
+ r = generic_array_bisect_one(f, a, last_index + 1, needle, test_object, direction, &left, &right, NULL);
+ if (r < 0 && r != -ENOANO)
+ return r;
}
for (;;) {
@@ -2928,26 +2935,9 @@ static int generic_array_bisect(
assert(left < right);
i = (left + right) / 2;
- p = journal_file_entry_array_item(f, array, i);
- if (p <= 0)
- r = -EBADMSG;
- else
- r = test_object(f, p, needle);
- if (IN_SET(r, -EBADMSG, -EADDRNOTAVAIL)) {
- log_debug_errno(r, "Encountered invalid entry while bisecting, cutting algorithm short. (2)");
- right = n = i;
- continue;
- }
- if (r < 0)
+ r = generic_array_bisect_one(f, a, i, needle, test_object, direction, &left, &right, NULL);
+ if (r < 0 && r != -ENOANO)
return r;
-
- if (r == TEST_FOUND)
- r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
-
- if (r == TEST_RIGHT)
- right = i;
- else
- left = i + 1;
}
}