Fixed issue when the hash length is zero (#2314)
* Fixed issue when the hash length is zero The following is illegal, even if no elements in the pointer are accessed: std::vector<my_struct> my_vec(0); // create an empty std::vector my_struct *ptr = &my_vec[0]; While this is a degenerate scenario, this should be fixed
This commit is contained in:
parent
46eb930948
commit
297bea495d
@ -468,15 +468,6 @@ image_init_result a78_cart_slot_device::call_load()
|
||||
}
|
||||
|
||||
|
||||
void a78_partialhash(util::hash_collection &dest, const unsigned char *data,
|
||||
unsigned long length, const char *functions)
|
||||
{
|
||||
if (length <= 128)
|
||||
return;
|
||||
dest.compute(&data[128], length - 128, functions);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
call_unload
|
||||
-------------------------------------------------*/
|
||||
|
@ -81,9 +81,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
void a78_partialhash(util::hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
|
||||
|
||||
|
||||
// ======================> a78_cart_slot_device
|
||||
|
||||
class a78_cart_slot_device : public device_t,
|
||||
@ -114,7 +111,7 @@ public:
|
||||
virtual bool is_reset_on_load() const override { return 1; }
|
||||
virtual const char *image_interface() const override { return "a7800_cart"; }
|
||||
virtual const char *file_extensions() const override { return "bin,a78"; }
|
||||
virtual device_image_partialhash_func get_partial_hash() const override { return &a78_partialhash; }
|
||||
virtual u32 unhashed_header_length() const override { return 128; }
|
||||
|
||||
// slot interface overrides
|
||||
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
|
||||
|
@ -1015,17 +1015,3 @@ WRITE8_MEMBER(nes_cart_slot_device::write_ex)
|
||||
m_cart->set_open_bus(((offset + 0x4020) & 0xff00) >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// partial hash function to be used by
|
||||
// device_image_partialhash_func
|
||||
//-------------------------------------------------
|
||||
|
||||
void nes_partialhash(util::hash_collection &dest, const unsigned char *data,
|
||||
unsigned long length, const char *functions)
|
||||
{
|
||||
if (length <= 16)
|
||||
return;
|
||||
dest.compute(&data[16], length - 16, functions);
|
||||
}
|
||||
|
@ -331,8 +331,6 @@ protected:
|
||||
std::vector<uint16_t> m_prg_bank_map;
|
||||
};
|
||||
|
||||
void nes_partialhash(util::hash_collection &dest, const unsigned char *data, unsigned long length, const char *functions);
|
||||
|
||||
// ======================> nes_cart_slot_device
|
||||
|
||||
class nes_cart_slot_device : public device_t,
|
||||
@ -364,7 +362,7 @@ public:
|
||||
virtual bool is_reset_on_load() const override { return 1; }
|
||||
virtual const char *image_interface() const override { return "nes_cart"; }
|
||||
virtual const char *file_extensions() const override { return "nes,unf,unif"; }
|
||||
virtual device_image_partialhash_func get_partial_hash() const override { return &nes_partialhash; }
|
||||
virtual u32 unhashed_header_length() const override { return 16; }
|
||||
|
||||
// slot interface overrides
|
||||
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
|
||||
|
@ -175,23 +175,6 @@ iodevice_t device_image_interface::device_typeid(const char *name)
|
||||
return (iodevice_t)-1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
device_compute_hash - compute a hash,
|
||||
using this device's partial hash if appropriate
|
||||
-------------------------------------------------*/
|
||||
|
||||
void device_image_interface::device_compute_hash(util::hash_collection &hashes, const void *data, size_t length, const char *types) const
|
||||
{
|
||||
/* retrieve the partial hash func */
|
||||
device_image_partialhash_func partialhash = get_partial_hash();
|
||||
|
||||
/* compute the hash */
|
||||
if (partialhash)
|
||||
partialhash(hashes, (const unsigned char*)data, length, types);
|
||||
else
|
||||
hashes.compute(reinterpret_cast<const u8 *>(data), length, types);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_image_filename - specifies the filename of
|
||||
// an image
|
||||
@ -513,37 +496,46 @@ bool device_image_interface::load_software_region(const char *tag, optional_shar
|
||||
// to be loaded
|
||||
// ****************************************************************************
|
||||
|
||||
void device_image_interface::run_hash(util::core_file &file, void (*partialhash)(util::hash_collection &, const unsigned char *, unsigned long, const char *),
|
||||
util::hash_collection &hashes, const char *types)
|
||||
bool device_image_interface::run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types)
|
||||
{
|
||||
u32 size;
|
||||
std::vector<u8> buf;
|
||||
|
||||
// reset the hash; we want to override existing data
|
||||
hashes.reset();
|
||||
size = (u32) file.size();
|
||||
|
||||
buf.resize(size);
|
||||
memset(&buf[0], 0, size);
|
||||
// figure out the size, and "cap" the skip bytes
|
||||
u64 size = file.size();
|
||||
skip_bytes = (u32) std::min((u64) skip_bytes, size);
|
||||
|
||||
// read the file
|
||||
file.seek(0, SEEK_SET);
|
||||
file.read(&buf[0], size);
|
||||
// seek to the beginning
|
||||
file.seek(skip_bytes, SEEK_SET);
|
||||
u64 position = skip_bytes;
|
||||
|
||||
if (partialhash)
|
||||
partialhash(hashes, &buf[0], size, types);
|
||||
else
|
||||
hashes.compute(&buf[0], size, types);
|
||||
// keep on reading hashes
|
||||
hashes.begin(types);
|
||||
while (position < size)
|
||||
{
|
||||
uint8_t buffer[8192];
|
||||
|
||||
// read bytes
|
||||
const u32 count = (u32) std::min(size - position, (u64) sizeof(buffer));
|
||||
const u32 actual_count = file.read(buffer, count);
|
||||
if (actual_count == 0)
|
||||
return false;
|
||||
position += actual_count;
|
||||
|
||||
// and compute the hashes
|
||||
hashes.buffer(buffer, actual_count);
|
||||
}
|
||||
hashes.end();
|
||||
|
||||
// cleanup
|
||||
file.seek(0, SEEK_SET);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void device_image_interface::image_checkhash()
|
||||
bool device_image_interface::image_checkhash()
|
||||
{
|
||||
device_image_partialhash_func partialhash;
|
||||
|
||||
// only calculate CRC if it hasn't been calculated, and the open_mode is read only
|
||||
u32 crcval;
|
||||
if (!m_hash.crc(crcval) && is_readonly() && !m_created)
|
||||
@ -551,29 +543,26 @@ void device_image_interface::image_checkhash()
|
||||
// do not cause a linear read of 600 megs please
|
||||
// TODO: use SHA1 in the CHD header as the hash
|
||||
if (image_type() == IO_CDROM)
|
||||
return;
|
||||
return true;
|
||||
|
||||
// Skip calculating the hash when we have an image mounted through a software list
|
||||
if (loaded_through_softlist())
|
||||
return;
|
||||
return true;
|
||||
|
||||
// retrieve the partial hash func
|
||||
partialhash = get_partial_hash();
|
||||
|
||||
run_hash(*m_file, partialhash, m_hash, util::hash_collection::HASH_TYPES_ALL);
|
||||
// run the hash
|
||||
if (!run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL))
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const
|
||||
{
|
||||
// retrieve the partial hash func
|
||||
device_image_partialhash_func partialhash = get_partial_hash();
|
||||
|
||||
// and calculate the hash
|
||||
// calculate the hash
|
||||
util::hash_collection hash;
|
||||
run_hash(file, partialhash, hash, util::hash_collection::HASH_TYPES_ALL);
|
||||
if (!run_hash(file, unhashed_header_length(), hash, util::hash_collection::HASH_TYPES_ALL))
|
||||
hash.reset();
|
||||
return hash;
|
||||
}
|
||||
|
||||
@ -1150,25 +1139,32 @@ image_init_result device_image_interface::finish_load()
|
||||
|
||||
if (m_is_loading)
|
||||
{
|
||||
image_checkhash();
|
||||
|
||||
if (m_created)
|
||||
if (!image_checkhash())
|
||||
{
|
||||
err = call_create(m_create_format, m_create_args);
|
||||
if (err != image_init_result::PASS)
|
||||
{
|
||||
if (!m_err)
|
||||
m_err = IMAGE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
m_err = IMAGE_ERROR_INVALIDIMAGE;
|
||||
err = image_init_result::FAIL;
|
||||
}
|
||||
else
|
||||
|
||||
if (err == image_init_result::PASS)
|
||||
{
|
||||
// using device load
|
||||
err = call_load();
|
||||
if (err != image_init_result::PASS)
|
||||
if (m_created)
|
||||
{
|
||||
if (!m_err)
|
||||
m_err = IMAGE_ERROR_UNSPECIFIED;
|
||||
err = call_create(m_create_format, m_create_args);
|
||||
if (err != image_init_result::PASS)
|
||||
{
|
||||
if (!m_err)
|
||||
m_err = IMAGE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// using device load
|
||||
err = call_load();
|
||||
if (err != image_init_result::PASS)
|
||||
{
|
||||
if (!m_err)
|
||||
m_err = IMAGE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +97,6 @@ enum class image_verify_result { PASS, FAIL };
|
||||
// device image interface function types
|
||||
typedef delegate<image_init_result (device_image_interface &)> device_image_load_delegate;
|
||||
typedef delegate<void (device_image_interface &)> device_image_func_delegate;
|
||||
// legacy
|
||||
typedef void (*device_image_partialhash_func)(util::hash_collection &, const unsigned char *, unsigned long, const char *);
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS
|
||||
@ -136,13 +134,11 @@ public:
|
||||
static const char *device_brieftypename(iodevice_t type);
|
||||
static iodevice_t device_typeid(const char *name);
|
||||
|
||||
virtual void device_compute_hash(util::hash_collection &hashes, const void *data, size_t length, const char *types) const;
|
||||
|
||||
virtual image_init_result call_load() { return image_init_result::PASS; }
|
||||
virtual image_init_result call_create(int format_type, util::option_resolution *format_options) { return image_init_result::PASS; }
|
||||
virtual void call_unload() { }
|
||||
virtual std::string call_display() { return std::string(); }
|
||||
virtual device_image_partialhash_func get_partial_hash() const { return nullptr; }
|
||||
virtual u32 unhashed_header_length() const { return 0; }
|
||||
virtual bool core_opens_image_file() const { return true; }
|
||||
virtual iodevice_t image_type() const = 0;
|
||||
virtual bool is_readable() const = 0;
|
||||
@ -267,7 +263,7 @@ protected:
|
||||
|
||||
void make_readonly() { m_readonly = true; }
|
||||
|
||||
void image_checkhash();
|
||||
bool image_checkhash();
|
||||
|
||||
const software_part *find_software_item(const std::string &identifier, bool restrict_to_interface, software_list_device **device = nullptr) const;
|
||||
std::string software_get_default_slot(const char *default_card_slot) const;
|
||||
@ -305,7 +301,7 @@ private:
|
||||
bool load_software_part(const std::string &identifier);
|
||||
|
||||
bool init_phase() const;
|
||||
static void run_hash(util::core_file &file, void(*partialhash)(util::hash_collection &, const unsigned char *, unsigned long, const char *), util::hash_collection &hashes, const char *types);
|
||||
static bool run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types);
|
||||
|
||||
// loads an image or software items and resets - called internally when we
|
||||
// load an is_reset_on_load() item
|
||||
|
Loading…
Reference in New Issue
Block a user