mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-10-23 17:30:52 +00:00
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:
@@ -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()));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user