Adding -fuzz_testing command line option, which disables the file data CRC16 check used by the -validate command. To fuzz testing using zzuf on Linux:

zzuf -d -c -s 1000000:2000000 ./basisu -validate -fuzz_testing kodim23.basis
This commit is contained in:
Rich Geldreich
2019-05-09 12:43:59 -07:00
parent c7e14a97fa
commit d7b22fc404
3 changed files with 92 additions and 10 deletions

View File

@@ -54,7 +54,7 @@ static void print_usage()
"Important: By default, the compressor assumes the input is in the sRGB colorspace (like photos/albedo textures).\n"
"If the input is NOT sRGB (like a normal map), be sure to specify -linear for less artifacts.\n"
"\n"
"Filenames prefixed with a @ symbol are read as filename listing files.\n"
"Filenames prefixed with a @ symbol are read as filename listing files, specifying which filenames to actually process.\n"
"\n"
"Options:\n"
" -file filename.png: Input image filename, multiple images are OK, use -file X for each input filename (prefixing input filenames with -file is optional)\n"
@@ -74,6 +74,7 @@ static void print_usage()
" (2d=arbitrary 2D images, 2darray=2D array, 3D=volume texture slices, video=video frames, cubemap=array of faces. For 2darray/3d/cubemaps/video, each source image's dimensions and # of mipmap levels must be the same.)\n"
" -framerate X: Set framerate in header to X/frames sec\n"
" -individual: Process input images individually and output multiple .basis files (not as a texture array)\n"
" -fuzz_testing: Use with -validate: Disables CRC16 validation of file contents before transcoding\n"
"\n"
"More options:\n"
" -max_endpoints X: Manually set the max number of color endpoint clusters from 1-16128, use instead of -q\n"
@@ -207,7 +208,8 @@ public:
m_multifile_first(0),
m_multifile_num(0),
m_individual(false),
m_no_ktx(false)
m_no_ktx(false),
m_fuzz_testing(false)
{
}
@@ -443,6 +445,8 @@ public:
}
else if (strcasecmp(pArg, "-individual") == 0)
m_individual = true;
else if (strcasecmp(pArg, "-fuzz_testing") == 0)
m_fuzz_testing = true;
else if (strcasecmp(pArg, "-csv_file") == 0)
{
REMAINING_ARGS_CHECK(1);
@@ -531,6 +535,7 @@ public:
bool m_individual;
bool m_no_ktx;
bool m_fuzz_testing;
};
static bool expand_multifile(command_line_params &opts)
@@ -790,22 +795,27 @@ static bool unpack_and_validate_mode(command_line_params &opts, bool validate_fl
basist::basisu_transcoder dec(&sel_codebook);
// Validate the file - note this isn't necessary for transcoding
if (!dec.validate_file_checksums(&basis_data[0], (uint32_t)basis_data.size(), true))
if (!opts.m_fuzz_testing)
{
error_printf("File version is unsupported, or file fail CRC checks!\n");
return false;
// Skip the full validation, which CRC16's the entire file.
// Validate the file - note this isn't necessary for transcoding
if (!dec.validate_file_checksums(&basis_data[0], (uint32_t)basis_data.size(), true))
{
error_printf("File version is unsupported, or file fail CRC checks!\n");
return false;
}
}
printf("File version and CRC checks succeeded\n");
basist::basisu_file_info fileinfo;
if (!dec.get_file_info(&basis_data[0], (uint32_t)basis_data.size(), fileinfo))
{
error_printf("Failed retrieving Basis file information!\n");
return false;
}
assert(fileinfo.m_total_images == fileinfo.m_image_mipmap_levels.size());
assert(fileinfo.m_total_images == dec.get_total_images(&basis_data[0], (uint32_t)basis_data.size()));

View File

@@ -3336,13 +3336,19 @@ namespace basist
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2a\n");
return false;
}
if (!sym_codec.read_huffman_table(inten_delta_model))
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2b\n");
return false;
}
if (!color5_delta_model0.is_valid() || !color5_delta_model1.is_valid() || !color5_delta_model2.is_valid() || !inten_delta_model.is_valid())
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 2b\n");
return false;
}
const bool endpoints_are_grayscale = sym_codec.get_bits(1) != 0;
m_endpoints.resize(num_endpoints);
@@ -3408,6 +3414,11 @@ namespace basist
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 6\n");
return false;
}
if (!mod_model.is_valid())
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 6a\n");
return false;
}
}
for (uint32_t i = 0; i < num_selectors; i++)
@@ -3445,6 +3456,11 @@ namespace basist
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7\n");
return false;
}
if (!uses_global_cb_bitflags_model.is_valid())
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 7a\n");
return false;
}
basist::huffman_decoding_table global_mod_indices_model;
if (mod_bits)
@@ -3454,6 +3470,11 @@ namespace basist
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8\n");
return false;
}
if (!global_mod_indices_model.is_valid())
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 8a\n");
return false;
}
}
uint32_t cur_uses_global_cb_bitflags = 0;
@@ -3519,7 +3540,16 @@ namespace basist
else
{
if (!sym_codec.read_huffman_table(delta_selector_pal_model))
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 10\n");
return false;
}
if ((num_selectors > 1) && (!delta_selector_pal_model.is_valid()))
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_palettes: fail 10a\n");
return false;
}
uint8_t prev_bytes[4] = { 0, 0, 0, 0 };
@@ -3574,10 +3604,22 @@ namespace basist
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1\n");
return false;
}
if (m_endpoint_pred_model.get_code_sizes().size() == 0)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1a\n");
return false;
}
if (!sym_codec.read_huffman_table(m_delta_endpoint_model))
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 1\n");
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 2\n");
return false;
}
if (m_delta_endpoint_model.get_code_sizes().size() == 0)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 2a\n");
return false;
}
@@ -3587,12 +3629,24 @@ namespace basist
return false;
}
if (m_selector_model.get_code_sizes().size() == 0)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 3a\n");
return false;
}
if (!sym_codec.read_huffman_table(m_selector_history_buf_rle_model))
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 4\n");
return false;
}
if (m_selector_history_buf_rle_model.get_code_sizes().size() == 0)
{
BASISU_DEVEL_ERROR("basisu_lowlevel_transcoder::decode_tables: fail 4a\n");
return false;
}
m_selector_history_buf_size = sym_codec.get_bits(13);
sym_codec.stop();
@@ -3791,6 +3845,16 @@ namespace basist
assert(m_selector_history_buf_size > 0);
int history_buf_index = selector_sym - (int)m_selectors.size();
if (history_buf_index >= (int)selector_history_buf.size())
{
// The file is corrupted or we've got a bug.
//console::error("rdo_etc1_lowlevel_decoder::transcode_slice: selector RLE value is too large!");
if (pPVRTC_work_mem)
free(pPVRTC_work_mem);
return false;
}
selector_index = selector_history_buf[history_buf_index];
if (history_buf_index != 0)
@@ -4310,6 +4374,12 @@ namespace basist
slice_info.m_unpacked_slice_crc16 = pSlice_descs[i].m_slice_data_crc16;
slice_info.m_alpha_flag = (pSlice_descs[i].m_flags & cSliceDescFlagsIsAlphaData) != 0;
if (pSlice_descs[i].m_image_index >= pHeader->m_total_images)
{
BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: slice desc's image index is invalid\n");
return false;
}
file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index] = basisu::maximum<uint32_t>(file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index], pSlice_descs[i].m_level_index + 1);
}

View File

@@ -162,6 +162,8 @@ namespace basist
const basisu::uint8_vec &get_code_sizes() const { return m_code_sizes; }
bool is_valid() const { return m_code_sizes.size() > 0; }
private:
basisu::uint8_vec m_code_sizes;
basisu::int_vec m_lookup;