@@ -81,34 +81,66 @@ filesystem_parser::find_image_offset(mmif& mm, file_off_t image_offset) {
8181 auto fh = mm.as <file_header>(pos);
8282
8383 if (fh->minor < 2 ) {
84- // best we can do for older file systems
85- return pos;
86- }
87-
88- // do a little more validation before we return
89- if (pos + sizeof (section_header_v2) >= mm.size ()) {
90- break ;
91- }
92-
93- auto sh = mm.as <section_header_v2>(pos);
94-
95- if (sh->number == 0 ) {
96- auto endpos = pos + sh->length + 2 * sizeof (section_header_v2);
97-
98- if (endpos < sh->length ) {
99- // overflow
84+ // v1 section header, presumably
85+ if (pos + sizeof (file_header) + sizeof (section_header) >= mm.size ()) {
10086 break ;
10187 }
10288
103- if (endpos >= mm.size ()) {
89+ auto sh = mm.as <section_header>(pos + sizeof (file_header));
90+
91+ // The only compression types supported before v0.3.0
92+ auto is_valid_compression = [](compression_type_v1 c) {
93+ return c == compression_type_v1::NONE ||
94+ c == compression_type_v1::LZMA ||
95+ c == compression_type_v1::ZSTD ||
96+ c == compression_type_v1::LZ4 || c == compression_type_v1::LZ4HC;
97+ };
98+
99+ // First section must be either a block or the metadata schema,
100+ // using a valid compression type.
101+ if ((sh->type == section_type::BLOCK ||
102+ sh->type == section_type::METADATA_V2_SCHEMA) &&
103+ is_valid_compression (sh->compression ) && sh->length > 0 ) {
104+ auto nextshpos =
105+ pos + sizeof (file_header) + sizeof (section_header) + sh->length ;
106+ if (nextshpos + sizeof (section_header) < mm.size ()) {
107+ auto nsh = mm.as <section_header>(nextshpos);
108+ // the next section must be a block or a metadata schema if the first
109+ // section was a block *or* a metadata block if the first section was
110+ // a metadata schema
111+ if ((sh->type == section_type::BLOCK
112+ ? nsh->type == section_type::BLOCK ||
113+ nsh->type == section_type::METADATA_V2_SCHEMA
114+ : nsh->type == section_type::METADATA_V2) &&
115+ is_valid_compression (nsh->compression ) && nsh->length > 0 ) {
116+ // we can be somewhat sure that this is where the filesystem starts
117+ return pos;
118+ }
119+ }
120+ }
121+ } else {
122+ // do a little more validation before we return
123+ if (pos + sizeof (section_header_v2) >= mm.size ()) {
104124 break ;
105125 }
106126
107- auto ps = mm.as <void >(pos + sh->length + sizeof (section_header_v2));
127+ auto sh = mm.as <section_header_v2>(pos);
128+
129+ if (sh->number == 0 ) {
130+ auto endpos = pos + sh->length + 2 * sizeof (section_header_v2);
131+
132+ if (endpos >= sh->length ) {
133+ if (endpos >= mm.size ()) {
134+ break ;
135+ }
136+
137+ auto ps = mm.as <void >(pos + sh->length + sizeof (section_header_v2));
108138
109- if (::memcmp (ps, magic.data (), magic.size ()) == 0 and
110- reinterpret_cast <section_header_v2 const *>(ps)->number == 1 ) {
111- return pos;
139+ if (::memcmp (ps, magic.data (), magic.size ()) == 0 and
140+ reinterpret_cast <section_header_v2 const *>(ps)->number == 1 ) {
141+ return pos;
142+ }
143+ }
112144 }
113145 }
114146
0 commit comments