1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-22 17:35:35 +03:00

fileio: make read_full_file_full() usable with size and READ_FULL_FILE_UNBASE64

When READ_FULL_FILE_UNBASE64 (or READ_FULL_FILE_UNHEX) is specified,
setting size argument by caller is difficult, as it is hard to estimate
the encoded length.

This makes when size is specified with decoding option, let's read file
more, and check decoded size later with the specified size.
This commit is contained in:
Yu Watanabe 2023-10-01 16:48:36 +09:00
parent b503c76689
commit 7e2a5fbd85

View File

@ -32,6 +32,8 @@
/* The maximum size of the file we'll read in one go in read_full_file() (64M). */
#define READ_FULL_BYTES_MAX (64U*1024U*1024U - 1U)
/* Used when a size is specified for read_full_file() with READ_FULL_FILE_UNBASE64 or _UNHEX */
#define READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY 3
/* The maximum size of virtual files (i.e. procfs, sysfs, and other virtual "API" files) we'll read in one go
* in read_virtual_file(). Note that this limit is different (and much lower) than the READ_FULL_BYTES_MAX
@ -572,7 +574,7 @@ int read_full_stream_full(
size_t *ret_size) {
_cleanup_free_ char *buf = NULL;
size_t n, n_next = 0, l;
size_t n, n_next = 0, l, expected_decoded_size = size;
int fd, r;
assert(f);
@ -583,6 +585,13 @@ int read_full_stream_full(
if (offset != UINT64_MAX && offset > LONG_MAX) /* fseek() can only deal with "long" offsets */
return -ERANGE;
if ((flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) != 0) {
if (size <= SIZE_MAX / READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY)
size *= READ_FULL_FILE_ENCODED_STRING_AMPLIFICATION_BOUNDARY;
else
size = SIZE_MAX;
}
fd = fileno(f);
if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see
* fmemopen()), let's optimize our buffering */
@ -707,6 +716,11 @@ int read_full_stream_full(
explicit_bzero_safe(buf, n);
free_and_replace(buf, decoded);
n = l = decoded_size;
if (FLAGS_SET(flags, READ_FULL_FILE_FAIL_WHEN_LARGER) && l > expected_decoded_size) {
r = -E2BIG;
goto finalize;
}
}
if (!ret_size) {