diff options
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 |
commit | 297bea495d0e62acb2cc609546b7da322cddf5b7 (patch) | |
tree | 1ce8dc10e1d40455e96f87e82778cece363a19f3 /src/emu/diimage.cpp | |
parent | 46eb9309484163f69c759d1c416b741a958f0549 (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
Diffstat (limited to 'src/emu/diimage.cpp')
-rw-r--r-- | src/emu/diimage.cpp | 118 |
1 files changed, 57 insertions, 61 deletions
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; + } } } } |