From: Pádraig Brady
Date: Mon, 8 Sep 2025 17:22:20 +0000 (+0100) Subject: basenc: ensure partial padding with newlines induces an error X-Git-Tag: v9.8~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d9b68362edcb509ecb00cf900617f55574212a96;p=thirdparty%2Fcoreutils.git basenc: ensure partial padding with newlines induces an error * src/basenc.c (has_padding): A more robust helper to identify padding in the presence of trailing newlines. (do_decode): Use has_padding() rather than just looking at the last character. * tests/basenc/base64.pl: Fully test commit v9.4-53-g378dc38f4 by ensuring partially padded data is diagnosed. baddecode9 is the case fixed in this commit. * NEWS: Mention the bug fix. --- diff --git a/NEWS b/NEWS index db9076c342..283d8046d5 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ GNU coreutils NEWS -*- outline -*- Previously it would have silently assumed 512 for any larger values. [bug introduced in coreutils-9.6] + 'base32' and 'base64' when decoding will again diagnose partially + padded data that ends with a newline. + [bug introduced in coreutils-9.5] + 'basenc -d -i' will now strip '=' characters from the input in encodings where padding characters are not valid. [bug introduced with the basenc program in coreutils-8.31] diff --git a/src/basenc.c b/src/basenc.c index 84789e2de9..090404ee4b 100644 --- a/src/basenc.c +++ b/src/basenc.c @@ -1446,6 +1446,22 @@ do_encode (FILE *in, char const *infile, FILE *out, idx_t wrap_column) finish_and_exit (in, infile); } +/* Returns TRUE if BUF of length LEN + ends with a '=' character. + Trailing '\n' characters are ignored. */ +ATTRIBUTE_PURE +static bool +has_padding (char const *buf, size_t len) +{ + while (len--) + { + if (buf[len] == '\n') + continue; + return buf[len] == '='; + } + return false; +} + static _Noreturn void do_decode (FILE *in, char const *infile, FILE *out, bool ignore_garbage) { @@ -1504,7 +1520,7 @@ do_decode (FILE *in, char const *infile, FILE *out, bool ignore_garbage) /* auto pad input (at eof). */ idx_t auto_padding = REQUIRED_PADDING (ctx.i); - if (auto_padding && (sum == 0 || inbuf[sum - 1] != '=')) + if (auto_padding && ! has_padding (inbuf, sum)) { affirm (auto_padding <= sizeof (padbuf)); IF_LINT (free (inbuf)); diff --git a/tests/basenc/base64.pl b/tests/basenc/base64.pl index 0aabc7b01b..9ba24cf47b 100755 --- a/tests/basenc/base64.pl +++ b/tests/basenc/base64.pl @@ -122,10 +122,12 @@ sub gen_tests($) if ($prog eq "base64") { push @Tests, ( + ['paddec1', '--decode', {IN=>'aQ'}, {OUT=>"i"}], + ['paddec2', '--decode', {IN=>'Zzw'}, {OUT=>"g<"}], + ['paddec3', '--decode', {IN=>'MTIzNA==MTIzNA'}, {OUT=>"12341234"}], + ['paddec4', '--decode', {IN=>"MTIzNA==\nMTIzNA"}, {OUT=>"12341234"}], ['baddecode', '--decode', {IN=>'a'}, {OUT=>""}, {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}], - ['paddecode2', '--decode', {IN=>'aQ'}, {OUT=>"i"}], - ['paddecode3', '--decode', {IN=>'Zzw'}, {OUT=>"g<"}], ['baddecode4', '--decode', {IN=>'Zz='}, {OUT=>"g"}, {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}], ['baddecode5', '--decode', {IN=>'Z==='}, {OUT=>""}, @@ -133,6 +135,10 @@ sub gen_tests($) ['baddecode6', '--decode', {IN=>'SB=='}, {OUT=>"H"}, {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}], ['baddecode7', '--decode', {IN=>'SGVsbG9='}, {OUT=>"Hello"}, + {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}], + ['baddecode8', '--decode', {IN=>'MTIzNA='}, {OUT=>"1234"}, + {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}], + ['baddecode9', '--decode', {IN=>"MTIzNA=\n"}, {OUT=>"1234"}, {ERR_SUBST => 's/.*: invalid input//'}, {ERR => "\n"}, {EXIT => 1}] ); }