| ... | @@ -107,19 +107,27 @@ pub fn decodeAlloc( | ... | @@ -107,19 +107,27 @@ pub fn decodeAlloc( |
| 107 | /// - `error.UnusedBitSet` if the unused bit of the frame header is set | 107 | /// - `error.UnusedBitSet` if the unused bit of the frame header is set |
| 108 | /// - `error.EndOfStream` if `src` does not contain a complete frame | 108 | /// - `error.EndOfStream` if `src` does not contain a complete frame |
| 109 | /// - an error in `block.Error` if there are errors decoding a block | 109 | /// - an error in `block.Error` if there are errors decoding a block |
| | 110 | /// - `error.SkippableSizeTooLarge` if the frame is skippable and reports a |
| | 111 | /// size greater than `src.len` |
| 110 | pub fn decodeFrame( | 112 | pub fn decodeFrame( |
| 111 | dest: []u8, | 113 | dest: []u8, |
| 112 | src: []const u8, | 114 | src: []const u8, |
| 113 | verify_checksum: bool, | 115 | verify_checksum: bool, |
| 114 | ) !ReadWriteCount { | 116 | ) !ReadWriteCount { |
| 115 | var fbs = std.io.fixedBufferStream(src); | 117 | var fbs = std.io.fixedBufferStream(src); |
| 116 | return switch (try decodeFrameType(fbs.reader())) { | 118 | switch (try decodeFrameType(fbs.reader())) { |
| 117 | .zstandard => decodeZstandardFrame(dest, src, verify_checksum), | 119 | .zstandard => return decodeZstandardFrame(dest, src, verify_checksum), |
| 118 | .skippable => ReadWriteCount{ | 120 | .skippable => { |
| 119 | .read_count = try fbs.reader().readIntLittle(u32) + 8, | 121 | const content_size = try fbs.reader().readIntLittle(u32); |
| 120 | .write_count = 0, | 122 | if (content_size > std.math.maxInt(usize) - 8) return error.SkippableSizeTooLarge; |
| | 123 | const read_count = @as(usize, content_size) + 8; |
| | 124 | if (read_count > src.len) return error.SkippableSizeTooLarge; |
| | 125 | return ReadWriteCount{ |
| | 126 | .read_count = read_count, |
| | 127 | .write_count = 0, |
| | 128 | }; |
| 121 | }, | 129 | }, |
| 122 | }; | 130 | } |
| 123 | } | 131 | } |
| 124 | | 132 | |
| 125 | pub const DecodeResult = struct { | 133 | pub const DecodeResult = struct { |
| ... | @@ -150,6 +158,8 @@ pub const DecodedFrame = union(enum) { | ... | @@ -150,6 +158,8 @@ pub const DecodedFrame = union(enum) { |
| 150 | /// - `error.EndOfStream` if `src` does not contain a complete frame | 158 | /// - `error.EndOfStream` if `src` does not contain a complete frame |
| 151 | /// - `error.OutOfMemory` if `allocator` cannot allocate enough memory | 159 | /// - `error.OutOfMemory` if `allocator` cannot allocate enough memory |
| 152 | /// - an error in `block.Error` if there are errors decoding a block | 160 | /// - an error in `block.Error` if there are errors decoding a block |
| | 161 | /// - `error.SkippableSizeTooLarge` if the frame is skippable and reports a |
| | 162 | /// size greater than `src.len` |
| 153 | pub fn decodeFrameAlloc( | 163 | pub fn decodeFrameAlloc( |
| 154 | allocator: Allocator, | 164 | allocator: Allocator, |
| 155 | src: []const u8, | 165 | src: []const u8, |
| ... | @@ -159,17 +169,23 @@ pub fn decodeFrameAlloc( | ... | @@ -159,17 +169,23 @@ pub fn decodeFrameAlloc( |
| 159 | var fbs = std.io.fixedBufferStream(src); | 169 | var fbs = std.io.fixedBufferStream(src); |
| 160 | const reader = fbs.reader(); | 170 | const reader = fbs.reader(); |
| 161 | const magic = try reader.readIntLittle(u32); | 171 | const magic = try reader.readIntLittle(u32); |
| 162 | return switch (try frameType(magic)) { | 172 | switch (try frameType(magic)) { |
| 163 | .zstandard => .{ | 173 | .zstandard => return .{ |
| 164 | .zstandard = try decodeZstandardFrameAlloc(allocator, src, verify_checksum, window_size_max), | 174 | .zstandard = try decodeZstandardFrameAlloc(allocator, src, verify_checksum, window_size_max), |
| 165 | }, | 175 | }, |
| 166 | .skippable => .{ | 176 | .skippable => { |
| 167 | .skippable = .{ | 177 | const content_size = try fbs.reader().readIntLittle(u32); |
| 168 | .magic_number = magic, | 178 | if (content_size > std.math.maxInt(usize) - 8) return error.SkippableSizeTooLarge; |
| 169 | .frame_size = try reader.readIntLittle(u32), | 179 | const read_count = @as(usize, content_size) + 8; |
| 170 | }, | 180 | if (read_count > src.len) return error.SkippableSizeTooLarge; |
| | 181 | return .{ |
| | 182 | .skippable = .{ |
| | 183 | .magic_number = magic, |
| | 184 | .frame_size = content_size, |
| | 185 | }, |
| | 186 | }; |
| 171 | }, | 187 | }, |
| 172 | }; | 188 | } |
| 173 | } | 189 | } |
| 174 | | 190 | |
| 175 | /// Returns the frame checksum corresponding to the data fed into `hasher` | 191 | /// Returns the frame checksum corresponding to the data fed into `hasher` |