| ... | ... | @@ -147,88 +147,85 @@ fn initFrame(d: *Decompress, window_size_max: usize, magic: Frame.Magic) !void { |
| 147 | 147 | fn readInFrame(d: *Decompress, bw: *BufferedWriter, limit: Reader.Limit, state: *State.InFrame) !usize { |
| 148 | 148 | const in = d.input; |
| 149 | 149 | |
| 150 | | var literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse = undefined; |
| 151 | | var match_fse_buffer: [zstd.table_size_max.match]Table.Fse = undefined; |
| 152 | | var offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse = undefined; |
| 153 | | var literals_buffer: [zstd.block_size_max]u8 = undefined; |
| 154 | | var sequence_buffer: [zstd.block_size_max]u8 = undefined; |
| 155 | | |
| 156 | | var decode: Frame.Zstandard.Decode = .init(&literal_fse_buffer, &match_fse_buffer, &offset_fse_buffer); |
| 157 | | |
| 158 | 150 | const header_bytes = try in.takeArray(3); |
| 159 | 151 | const block_header: Frame.Zstandard.Block.Header = @bitCast(header_bytes.*); |
| 160 | 152 | const block_size = block_header.size; |
| 161 | 153 | if (state.frame.block_size_max < block_size) return error.BlockOversize; |
| 162 | 154 | if (@intFromEnum(limit) < block_size) return error.OutputBufferUndersize; |
| 155 | var bytes_written: usize = 0; |
| 163 | 156 | switch (block_header.type) { |
| 164 | 157 | .raw => { |
| 165 | 158 | try in.readAll(bw, .limited(block_size)); |
| 166 | | return block_size; |
| 159 | bytes_written = block_size; |
| 167 | 160 | }, |
| 168 | 161 | .rle => { |
| 169 | 162 | const byte = try in.takeByte(); |
| 170 | 163 | try bw.splatByteAll(byte, block_size); |
| 171 | | return block_size; |
| 164 | bytes_written = block_size; |
| 172 | 165 | }, |
| 173 | | .compressed => {}, |
| 174 | | .reserved => return error.ReservedBlock, |
| 175 | | } |
| 166 | .compressed => { |
| 167 | var literal_fse_buffer: [zstd.table_size_max.literal]Table.Fse = undefined; |
| 168 | var match_fse_buffer: [zstd.table_size_max.match]Table.Fse = undefined; |
| 169 | var offset_fse_buffer: [zstd.table_size_max.offset]Table.Fse = undefined; |
| 170 | var literals_buffer: [zstd.block_size_max]u8 = undefined; |
| 171 | var sequence_buffer: [zstd.block_size_max]u8 = undefined; |
| 172 | var decode: Frame.Zstandard.Decode = .init(&literal_fse_buffer, &match_fse_buffer, &offset_fse_buffer); |
| 173 | var remaining: Reader.Limit = .limited(block_size); |
| 174 | const literals = try LiteralsSection.decode(in, &remaining, &literals_buffer); |
| 175 | const sequences_header = try SequencesSection.Header.decode(in, &remaining); |
| 176 | |
| 177 | try decode.prepare(in, &remaining, literals, sequences_header); |
| 178 | |
| 179 | { |
| 180 | if (sequence_buffer.len < @intFromEnum(remaining)) |
| 181 | return error.SequenceBufferUndersize; |
| 182 | const seq_slice = remaining.slice(&sequence_buffer); |
| 183 | try in.readSlice(seq_slice); |
| 184 | var bit_stream = try ReverseBitReader.init(seq_slice); |
| 176 | 185 | |
| 177 | | var remaining: Reader.Limit = .limited(block_size); |
| 178 | | const literals = try LiteralsSection.decode(in, &remaining, &literals_buffer); |
| 179 | | const sequences_header = try SequencesSection.Header.decode(in, &remaining); |
| 186 | if (sequences_header.sequence_count > 0) { |
| 187 | try decode.readInitialFseState(&bit_stream); |
| 188 | |
| 189 | var sequence_size_limit = state.frame.block_size_max; |
| 190 | for (0..sequences_header.sequence_count) |i| { |
| 191 | const decompressed_size = try decode.decodeSequence( |
| 192 | bw, |
| 193 | &bit_stream, |
| 194 | sequence_size_limit, |
| 195 | i == sequences_header.sequence_count - 1, |
| 196 | ); |
| 197 | sequence_size_limit -= decompressed_size; |
| 198 | bytes_written += decompressed_size; |
| 199 | } |
| 200 | } |
| 180 | 201 | |
| 181 | | try decode.prepare(in, &remaining, literals, sequences_header); |
| 202 | if (!bit_stream.isEmpty()) { |
| 203 | return error.MalformedCompressedBlock; |
| 204 | } |
| 205 | } |
| 182 | 206 | |
| 183 | | var bytes_written: usize = 0; |
| 184 | | { |
| 185 | | if (sequence_buffer.len < @intFromEnum(remaining)) |
| 186 | | return error.SequenceBufferUndersize; |
| 187 | | const seq_slice = remaining.slice(&sequence_buffer); |
| 188 | | try in.readSlice(seq_slice); |
| 189 | | var bit_stream = try ReverseBitReader.init(seq_slice); |
| 190 | | |
| 191 | | if (sequences_header.sequence_count > 0) { |
| 192 | | try decode.readInitialFseState(&bit_stream); |
| 193 | | |
| 194 | | var sequence_size_limit = state.frame.block_size_max; |
| 195 | | for (0..sequences_header.sequence_count) |i| { |
| 196 | | const decompressed_size = try decode.decodeSequence( |
| 197 | | bw, |
| 198 | | &bit_stream, |
| 199 | | sequence_size_limit, |
| 200 | | i == sequences_header.sequence_count - 1, |
| 201 | | ); |
| 202 | | sequence_size_limit -= decompressed_size; |
| 203 | | bytes_written += decompressed_size; |
| 207 | if (decode.literal_written_count < literals.header.regenerated_size) { |
| 208 | const len = literals.header.regenerated_size - decode.literal_written_count; |
| 209 | try decode.decodeLiterals(bw, len); |
| 210 | bytes_written += len; |
| 204 | 211 | } |
| 205 | | } |
| 206 | 212 | |
| 207 | | if (!bit_stream.isEmpty()) { |
| 208 | | return error.MalformedCompressedBlock; |
| 209 | | } |
| 210 | | } |
| 213 | switch (decode.literal_header.block_type) { |
| 214 | .treeless, .compressed => { |
| 215 | if (!decode.isLiteralStreamEmpty()) return error.MalformedCompressedBlock; |
| 216 | }, |
| 217 | .raw, .rle => {}, |
| 218 | } |
| 211 | 219 | |
| 212 | | if (decode.literal_written_count < literals.header.regenerated_size) { |
| 213 | | const len = literals.header.regenerated_size - decode.literal_written_count; |
| 214 | | try decode.decodeLiterals(bw, len); |
| 215 | | bytes_written += len; |
| 216 | | } |
| 220 | if (bytes_written > state.frame.block_size_max) return error.BlockOversize; |
| 221 | if (remaining.nonzero()) return error.MalformedCompressedBlock; |
| 217 | 222 | |
| 218 | | switch (decode.literal_header.block_type) { |
| 219 | | .treeless, .compressed => { |
| 220 | | if (!decode.isLiteralStreamEmpty()) return error.MalformedCompressedBlock; |
| 223 | state.decompressed_size += bytes_written; |
| 224 | if (state.frame.content_size) |size| { |
| 225 | if (state.decompressed_size > size) return error.MalformedFrame; |
| 226 | } |
| 221 | 227 | }, |
| 222 | | .raw, .rle => {}, |
| 223 | | } |
| 224 | | |
| 225 | | if (bytes_written > state.frame.block_size_max) return error.BlockOversize; |
| 226 | | if (remaining.nonzero()) return error.MalformedCompressedBlock; |
| 227 | | |
| 228 | | state.decompressed_size += bytes_written; |
| 229 | | |
| 230 | | if (state.frame.content_size) |size| { |
| 231 | | if (state.decompressed_size > size) return error.MalformedFrame; |
| 228 | .reserved => return error.ReservedBlock, |
| 232 | 229 | } |
| 233 | 230 | |
| 234 | 231 | if (state.frame.hasher_opt) |*hasher| { |