summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author npwoods <npwoods@alumni.carnegiemellon.edu>2017-05-27 21:23:45 -0400
committer Vas Crabb <cuavas@users.noreply.github.com>2017-05-28 11:23:45 +1000
commit297bea495d0e62acb2cc609546b7da322cddf5b7 (patch)
tree1ce8dc10e1d40455e96f87e82778cece363a19f3
parent46eb9309484163f69c759d1c416b741a958f0549 (diff)
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
-rw-r--r--src/devices/bus/a7800/a78_slot.cpp9
-rw-r--r--src/devices/bus/a7800/a78_slot.h5
-rw-r--r--src/devices/bus/nes/nes_slot.cpp14
-rw-r--r--src/devices/bus/nes/nes_slot.h4
-rw-r--r--src/emu/diimage.cpp118
-rw-r--r--src/emu/diimage.h10
6 files changed, 62 insertions, 98 deletions
diff --git a/src/devices/bus/a7800/a78_slot.cpp b/src/devices/bus/a7800/a78_slot.cpp
index 78749155cbb..e33048ec40c 100644
--- a/src/devices/bus/a7800/a78_slot.cpp
+++ b/src/devices/bus/a7800/a78_slot.cpp
@@ -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
-------------------------------------------------*/
diff --git a/src/devices/bus/a7800/a78_slot.h b/src/devices/bus/a7800/a78_slot.h
index e498f416e54..7a5e6b26260 100644
--- a/src/devices/bus/a7800/a78_slot.h
+++ b/src/devices/bus/a7800/a78_slot.h
@@ -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;
diff --git a/src/devices/bus/nes/nes_slot.cpp b/src/devices/bus/nes/nes_slot.cpp
index b8f99355faa..2676ad357a7 100644
--- a/src/devices/bus/nes/nes_slot.cpp
+++ b/src/devices/bus/nes/nes_slot.cpp
@@ -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);
-}
diff --git a/src/devices/bus/nes/nes_slot.h b/src/devices/bus/nes/nes_slot.h
index 82876ce15a5..088c402803c 100644
--- a/src/devices/bus/nes/nes_slot.h
+++ b/src/devices/bus/nes/nes_slot.h
@@ -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;
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 28dad1f82ee..64b09a101f2 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -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;
-
- // retrieve the partial hash func
- partialhash = get_partial_hash();
+ return true;
- 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 (!image_checkhash())
+ {
+ m_err = IMAGE_ERROR_INVALIDIMAGE;
+ err = image_init_result::FAIL;
+ }
- if (m_created)
+ if (err == image_init_result::PASS)
{
- err = call_create(m_create_format, m_create_args);
- 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)
+ else
{
- if (!m_err)
- m_err = IMAGE_ERROR_UNSPECIFIED;
+ // using device load
+ err = call_load();
+ if (err != image_init_result::PASS)
+ {
+ if (!m_err)
+ m_err = IMAGE_ERROR_UNSPECIFIED;
+ }
}
}
}
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
index 1f716075451..19b7b18292b 100644
--- a/src/emu/diimage.h
+++ b/src/emu/diimage.h
@@ -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