mirror of
https://github.com/systemd/systemd.git
synced 2026-06-30 19:57:29 +00:00
Couple of hardening changes for utils flagged by kres (#42732)
This commit is contained in:
@@ -287,6 +287,12 @@ static size_t previous_ansi_sequence(const char *s, size_t length, const char **
|
||||
|
||||
/* Locate the previous ANSI sequence and save its start in *ret_where and return length. */
|
||||
|
||||
if (length < 2) {
|
||||
/* Need at least two bytes for an ANSI sequence */
|
||||
*ret_where = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = length - 2; i > 0; i--) { /* -2 because at least two bytes are needed */
|
||||
size_t slen = ansi_sequence_length(s + (i - 1), length - (i - 1));
|
||||
if (slen == 0)
|
||||
|
||||
@@ -395,9 +395,18 @@ int uid_range_partition(UIDRange *range, uid_t size) {
|
||||
if (n_new_entries > range->n_entries && !GREEDY_REALLOC(range->entries, n_new_entries))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Work backwards to avoid overwriting entries we still need to read */
|
||||
/* Compact in place: drop entries that contribute zero partitions (nr < size). This forward pass
|
||||
* reads each entry once and only writes to lower-or-equal indices, so it cannot alias an unread
|
||||
* source entry. */
|
||||
size_t n_src = 0;
|
||||
for (size_t i = 0; i < range->n_entries; i++)
|
||||
if (range->entries[i].nr >= size)
|
||||
range->entries[n_src++] = range->entries[i];
|
||||
|
||||
/* Pre-compaction guarantees every surviving entry contributes at least one partition slot, so the
|
||||
* write cursor t stays ahead of the read index. */
|
||||
size_t t = n_new_entries;
|
||||
for (size_t i = range->n_entries; i > 0; i--) {
|
||||
for (size_t i = n_src; i > 0; i--) {
|
||||
UIDRangeEntry *e = range->entries + i - 1;
|
||||
unsigned n_parts = e->nr / size;
|
||||
|
||||
|
||||
@@ -9,6 +9,17 @@
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(ellipsize_mem_ansi_short) {
|
||||
_cleanup_free_ char *a = ellipsize_mem("X\x1b[m", 4, 1, 50);
|
||||
assert_se(a);
|
||||
|
||||
_cleanup_free_ char *b = ellipsize_mem(" \x1b[A", 4, 1, 0);
|
||||
assert_se(b);
|
||||
|
||||
_cleanup_free_ char *c = ellipsize_mem("\x1b[m", 3, 1, 50);
|
||||
assert_se(c);
|
||||
}
|
||||
|
||||
TEST(xsprintf) {
|
||||
char buf[5];
|
||||
|
||||
|
||||
@@ -318,6 +318,68 @@ TEST(uid_range_partition) {
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
/* Small entry preceding a large entry: the small entry must be dropped and the large entry
|
||||
* partitioned without the in-place backward-fill write cursor aliasing the still-live small entry
|
||||
* slot. */
|
||||
ASSERT_OK(uid_range_add_str(&p, "0-4"));
|
||||
ASSERT_OK(uid_range_add_str(&p, "100-129"));
|
||||
ASSERT_EQ(uid_range_entries(p), 2U);
|
||||
ASSERT_OK(uid_range_partition(p, 10));
|
||||
ASSERT_EQ(uid_range_entries(p), 3U);
|
||||
ASSERT_EQ(p->entries[0].start, 100U);
|
||||
ASSERT_EQ(p->entries[0].nr, 10U);
|
||||
ASSERT_EQ(p->entries[1].start, 110U);
|
||||
ASSERT_EQ(p->entries[1].nr, 10U);
|
||||
ASSERT_EQ(p->entries[2].start, 120U);
|
||||
ASSERT_EQ(p->entries[2].nr, 10U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
/* A too-small entry between two partitionable entries is dropped; the others still partition. */
|
||||
ASSERT_OK(uid_range_add_str(&p, "0-4")); /* nr=5 < size -> dropped */
|
||||
ASSERT_OK(uid_range_add_str(&p, "50-69")); /* nr=20 -> 2 parts */
|
||||
ASSERT_OK(uid_range_add_str(&p, "200-204")); /* nr=5 < size -> dropped */
|
||||
ASSERT_OK(uid_range_add_str(&p, "1000-1029")); /* nr=30 -> 3 parts */
|
||||
ASSERT_EQ(uid_range_entries(p), 4U);
|
||||
ASSERT_OK(uid_range_partition(p, 10));
|
||||
ASSERT_EQ(uid_range_entries(p), 5U);
|
||||
ASSERT_EQ(p->entries[0].start, 50U);
|
||||
ASSERT_EQ(p->entries[0].nr, 10U);
|
||||
ASSERT_EQ(p->entries[1].start, 60U);
|
||||
ASSERT_EQ(p->entries[1].nr, 10U);
|
||||
ASSERT_EQ(p->entries[2].start, 1000U);
|
||||
ASSERT_EQ(p->entries[2].nr, 10U);
|
||||
ASSERT_EQ(p->entries[3].start, 1010U);
|
||||
ASSERT_EQ(p->entries[3].nr, 10U);
|
||||
ASSERT_EQ(p->entries[4].start, 1020U);
|
||||
ASSERT_EQ(p->entries[4].nr, 10U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
/* A too-small entry before a partitionable entry is dropped. */
|
||||
ASSERT_OK(uid_range_add_str(&p, "0-4")); /* nr=5 < size -> dropped */
|
||||
ASSERT_OK(uid_range_add_str(&p, "100-119")); /* nr=20 -> 2 parts */
|
||||
ASSERT_OK(uid_range_partition(p, 10));
|
||||
ASSERT_EQ(uid_range_entries(p), 2U);
|
||||
ASSERT_EQ(p->entries[0].start, 100U);
|
||||
ASSERT_EQ(p->entries[0].nr, 10U);
|
||||
ASSERT_EQ(p->entries[1].start, 110U);
|
||||
ASSERT_EQ(p->entries[1].nr, 10U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
/* A too-small entry after a partitionable entry is dropped. */
|
||||
ASSERT_OK(uid_range_add_str(&p, "0-199")); /* nr=200 -> 2 parts */
|
||||
ASSERT_OK(uid_range_add_str(&p, "1000-1004")); /* nr=5 < size -> dropped */
|
||||
ASSERT_OK(uid_range_partition(p, 100));
|
||||
ASSERT_EQ(uid_range_entries(p), 2U);
|
||||
ASSERT_EQ(p->entries[0].start, 0U);
|
||||
ASSERT_EQ(p->entries[0].nr, 100U);
|
||||
ASSERT_EQ(p->entries[1].start, 100U);
|
||||
ASSERT_EQ(p->entries[1].nr, 100U);
|
||||
|
||||
p = uid_range_free(p);
|
||||
|
||||
/* Partition size of 1 */
|
||||
ASSERT_OK(uid_range_add_str(&p, "100-102"));
|
||||
ASSERT_OK(uid_range_partition(p, 1));
|
||||
|
||||
Reference in New Issue
Block a user