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
|
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
|
// ======================> a78_cart_slot_device
|
||||||
|
|
||||||
class a78_cart_slot_device : public device_t,
|
class a78_cart_slot_device : public device_t,
|
||||||
@ -114,7 +111,7 @@ public:
|
|||||||
virtual bool is_reset_on_load() const override { return 1; }
|
virtual bool is_reset_on_load() const override { return 1; }
|
||||||
virtual const char *image_interface() const override { return "a7800_cart"; }
|
virtual const char *image_interface() const override { return "a7800_cart"; }
|
||||||
virtual const char *file_extensions() const override { return "bin,a78"; }
|
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
|
// slot interface overrides
|
||||||
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
|
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);
|
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;
|
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
|
// ======================> nes_cart_slot_device
|
||||||
|
|
||||||
class nes_cart_slot_device : public device_t,
|
class nes_cart_slot_device : public device_t,
|
||||||
@ -364,7 +362,7 @@ public:
|
|||||||
virtual bool is_reset_on_load() const override { return 1; }
|
virtual bool is_reset_on_load() const override { return 1; }
|
||||||
virtual const char *image_interface() const override { return "nes_cart"; }
|
virtual const char *image_interface() const override { return "nes_cart"; }
|
||||||
virtual const char *file_extensions() const override { return "nes,unf,unif"; }
|
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
|
// slot interface overrides
|
||||||
virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
|
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;
|
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
|
// set_image_filename - specifies the filename of
|
||||||
// an image
|
// an image
|
||||||
@ -513,37 +496,46 @@ bool device_image_interface::load_software_region(const char *tag, optional_shar
|
|||||||
// to be loaded
|
// 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 *),
|
bool device_image_interface::run_hash(util::core_file &file, u32 skip_bytes, util::hash_collection &hashes, const char *types)
|
||||||
util::hash_collection &hashes, const char *types)
|
|
||||||
{
|
{
|
||||||
u32 size;
|
// reset the hash; we want to override existing data
|
||||||
std::vector<u8> buf;
|
|
||||||
|
|
||||||
hashes.reset();
|
hashes.reset();
|
||||||
size = (u32) file.size();
|
|
||||||
|
|
||||||
buf.resize(size);
|
// figure out the size, and "cap" the skip bytes
|
||||||
memset(&buf[0], 0, size);
|
u64 size = file.size();
|
||||||
|
skip_bytes = (u32) std::min((u64) skip_bytes, size);
|
||||||
|
|
||||||
// read the file
|
// seek to the beginning
|
||||||
file.seek(0, SEEK_SET);
|
file.seek(skip_bytes, SEEK_SET);
|
||||||
file.read(&buf[0], size);
|
u64 position = skip_bytes;
|
||||||
|
|
||||||
if (partialhash)
|
// keep on reading hashes
|
||||||
partialhash(hashes, &buf[0], size, types);
|
hashes.begin(types);
|
||||||
else
|
while (position < size)
|
||||||
hashes.compute(&buf[0], size, types);
|
{
|
||||||
|
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
|
// cleanup
|
||||||
file.seek(0, SEEK_SET);
|
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
|
// only calculate CRC if it hasn't been calculated, and the open_mode is read only
|
||||||
u32 crcval;
|
u32 crcval;
|
||||||
if (!m_hash.crc(crcval) && is_readonly() && !m_created)
|
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
|
// do not cause a linear read of 600 megs please
|
||||||
// TODO: use SHA1 in the CHD header as the hash
|
// TODO: use SHA1 in the CHD header as the hash
|
||||||
if (image_type() == IO_CDROM)
|
if (image_type() == IO_CDROM)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
// Skip calculating the hash when we have an image mounted through a software list
|
// Skip calculating the hash when we have an image mounted through a software list
|
||||||
if (loaded_through_softlist())
|
if (loaded_through_softlist())
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
// retrieve the partial hash func
|
// run the hash
|
||||||
partialhash = get_partial_hash();
|
if (!run_hash(*m_file, unhashed_header_length(), m_hash, util::hash_collection::HASH_TYPES_ALL))
|
||||||
|
return false;
|
||||||
run_hash(*m_file, partialhash, m_hash, util::hash_collection::HASH_TYPES_ALL);
|
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const
|
util::hash_collection device_image_interface::calculate_hash_on_file(util::core_file &file) const
|
||||||
{
|
{
|
||||||
// retrieve the partial hash func
|
// calculate the hash
|
||||||
device_image_partialhash_func partialhash = get_partial_hash();
|
|
||||||
|
|
||||||
// and calculate the hash
|
|
||||||
util::hash_collection 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;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1150,8 +1139,14 @@ image_init_result device_image_interface::finish_load()
|
|||||||
|
|
||||||
if (m_is_loading)
|
if (m_is_loading)
|
||||||
{
|
{
|
||||||
image_checkhash();
|
if (!image_checkhash())
|
||||||
|
{
|
||||||
|
m_err = IMAGE_ERROR_INVALIDIMAGE;
|
||||||
|
err = image_init_result::FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == image_init_result::PASS)
|
||||||
|
{
|
||||||
if (m_created)
|
if (m_created)
|
||||||
{
|
{
|
||||||
err = call_create(m_create_format, m_create_args);
|
err = call_create(m_create_format, m_create_args);
|
||||||
@ -1172,6 +1167,7 @@ image_init_result device_image_interface::finish_load()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_is_loading = false;
|
m_is_loading = false;
|
||||||
m_create_format = 0;
|
m_create_format = 0;
|
||||||
m_create_args = nullptr;
|
m_create_args = nullptr;
|
||||||
|
@ -97,8 +97,6 @@ enum class image_verify_result { PASS, FAIL };
|
|||||||
// device image interface function types
|
// device image interface function types
|
||||||
typedef delegate<image_init_result (device_image_interface &)> device_image_load_delegate;
|
typedef delegate<image_init_result (device_image_interface &)> device_image_load_delegate;
|
||||||
typedef delegate<void (device_image_interface &)> device_image_func_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
|
// MACROS
|
||||||
@ -136,13 +134,11 @@ public:
|
|||||||
static const char *device_brieftypename(iodevice_t type);
|
static const char *device_brieftypename(iodevice_t type);
|
||||||
static iodevice_t device_typeid(const char *name);
|
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_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 image_init_result call_create(int format_type, util::option_resolution *format_options) { return image_init_result::PASS; }
|
||||||
virtual void call_unload() { }
|
virtual void call_unload() { }
|
||||||
virtual std::string call_display() { return std::string(); }
|
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 bool core_opens_image_file() const { return true; }
|
||||||
virtual iodevice_t image_type() const = 0;
|
virtual iodevice_t image_type() const = 0;
|
||||||
virtual bool is_readable() const = 0;
|
virtual bool is_readable() const = 0;
|
||||||
@ -267,7 +263,7 @@ protected:
|
|||||||
|
|
||||||
void make_readonly() { m_readonly = true; }
|
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;
|
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;
|
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 load_software_part(const std::string &identifier);
|
||||||
|
|
||||||
bool init_phase() const;
|
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
|
// loads an image or software items and resets - called internally when we
|
||||||
// load an is_reset_on_load() item
|
// load an is_reset_on_load() item
|
||||||
|
Loading…
Reference in New Issue
Block a user