1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-27 01:55:32 +03:00

Merge pull request #11223 from poettering/read-line-0x00-0xff

fileio: fix read_one_line() when reading bytes > 0x7F
This commit is contained in:
Lennart Poettering 2018-12-20 14:53:23 +01:00 committed by GitHub
commit 614bf4131b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 9 deletions

View File

@ -755,9 +755,15 @@ int read_line_full(FILE *f, size_t limit, ReadLineFlags flags, char **ret) {
(eol == EOL_NONE && previous_eol != EOL_NONE) ||
(eol != EOL_NONE && (previous_eol & eol) != 0)) {
/* Previous char was a NUL? This is not an EOL, but the previous char was? This type of
* EOL marker has been seen right before? In either of these three cases we are
* done. But first, let's put this character back in the queue. */
assert_se(ungetc(c, f) != EOF);
* EOL marker has been seen right before? In either of these three cases we are
* done. But first, let's put this character back in the queue. (Note that we have to
* cast this to (unsigned char) here as ungetc() expects a positive 'int', and if we
* are on an architecture where 'char' equals 'signed char' we need to ensure we don't
* pass a negative value here. That said, to complicate things further ungetc() is
* actually happy with most negative characters and implicitly casts them back to
* positive ones as needed, except for \xff (aka -1, aka EOF), which it refuses. What a
* godawful API!) */
assert_se(ungetc((unsigned char) c, f) != EOF);
break;
}

View File

@ -611,7 +611,7 @@ static void test_tempfn(void) {
}
static const char chars[] =
"Aąę„”\n";
"Aąę„”\n\377";
static void test_fgetc(void) {
_cleanup_fclose_ FILE *f = NULL;
@ -624,11 +624,12 @@ static void test_fgetc(void) {
assert_se(safe_fgetc(f, &c) == 1);
assert_se(c == chars[i]);
assert_se(ungetc(c, f) != EOF);
assert_se(safe_fgetc(f, &c) == 1);
/* EOF is -1, and hence we can't push value 255 in this way */
assert_se(ungetc(c, f) != EOF || c == EOF);
assert_se(c == EOF || safe_fgetc(f, &c) == 1);
assert_se(c == chars[i]);
/* Check that ungetc doesn't care about unsigned char vs signed char */
/* But it works when we push it properly cast */
assert_se(ungetc((unsigned char) c, f) != EOF);
assert_se(safe_fgetc(f, &c) == 1);
assert_se(c == chars[i]);
@ -778,7 +779,7 @@ static void test_read_line4(void) {
static void test_read_nul_string(void) {
static const char test[] = "string nr. 1\0"
"string nr. 2\n\0"
"empty string follows\0"
"\377empty string follows\0"
"\0"
"final string\n is empty\0"
"\0";
@ -794,7 +795,7 @@ static void test_read_nul_string(void) {
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 14 && streq_ptr(s, "string nr. 2\n"));
s = mfree(s);
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 21 && streq_ptr(s, "empty string follows"));
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 22 && streq_ptr(s, "\377empty string follows"));
s = mfree(s);
assert_se(read_nul_string(f, LONG_LINE_MAX, &s) == 1 && streq_ptr(s, ""));