mirror of
https://github.com/str4d/rage.git
synced 2025-04-03 19:07:42 +03:00
age-core: Reject invalid last lines in AgeStanza
bodies
The length of a Base64 encoding can never be 1 mod 4, because that only provides six of the eight bits necessary for encoding a byte. Previously we checked that every line was valid Base64 (which works because all lines except the last are 64 characters, which exactly encodes 48 bytes). In 0.7.0 we improved the parser efficiency by only running the Base64 decoder lazily. We replaced the per-line check with an `is_base64_char` check, but forgot to reject the invalid subset of last-line lengths.
This commit is contained in:
parent
349b4c31cb
commit
8da15148fc
1 changed files with 12 additions and 5 deletions
|
@ -134,7 +134,7 @@ pub mod read {
|
|||
branch::alt,
|
||||
bytes::streaming::{tag, take_while1, take_while_m_n},
|
||||
character::streaming::newline,
|
||||
combinator::{map, map_opt, opt},
|
||||
combinator::{map, map_opt, opt, verify},
|
||||
multi::{many_till, separated_list1},
|
||||
sequence::{pair, preceded, terminated},
|
||||
IResult,
|
||||
|
@ -169,8 +169,12 @@ pub mod read {
|
|||
many_till(
|
||||
// Any body lines before the last MUST be full-length.
|
||||
terminated(take_while_m_n(64, 64, is_base64_char), newline),
|
||||
// Last body line MUST be short (empty if necessary).
|
||||
terminated(take_while_m_n(0, 63, is_base64_char), newline),
|
||||
// Last body line MUST be short (empty if necessary), and MUST be a valid
|
||||
// Base64 length (i.e. the length must not be 1 mod 4).
|
||||
verify(
|
||||
terminated(take_while_m_n(0, 63, is_base64_char), newline),
|
||||
|line: &[u8]| line.len() % 4 != 1,
|
||||
),
|
||||
),
|
||||
|(full_chunks, partial_chunk): (Vec<&[u8]>, &[u8])| {
|
||||
let mut chunks = full_chunks;
|
||||
|
@ -185,9 +189,12 @@ pub mod read {
|
|||
separated_list1(newline, take_while1(is_base64_char)),
|
||||
|chunks: Vec<&[u8]>| {
|
||||
// Enforce that the only chunk allowed to be shorter than 64 characters
|
||||
// is the last chunk.
|
||||
// is the last chunk, and that its length must not be 1 mod 4.
|
||||
let (partial_chunk, full_chunks) = chunks.split_last().unwrap();
|
||||
if full_chunks.iter().any(|s| s.len() != 64) || partial_chunk.len() > 64 {
|
||||
if full_chunks.iter().any(|s| s.len() != 64)
|
||||
|| partial_chunk.len() > 64
|
||||
|| partial_chunk.len() % 4 == 1
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some(chunks)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue