chdman.cpp: fix for code that expects to be able to dereference a pointer that it knows may be null (Vas Crabb)

This commit is contained in:
Ivan Vangelista 2016-04-27 10:27:46 +02:00
parent cfee536f22
commit 00fd6ba0bd

View File

@ -25,6 +25,10 @@
#include <ctype.h> #include <ctype.h>
#include <iostream> #include <iostream>
#include <cassert>
#include <cstring>
#include <limits>
#include <memory>
#include <new> #include <new>
#include <unordered_map> #include <unordered_map>
@ -191,19 +195,52 @@ private:
}; };
// ======================> chd_zero_compressor
class chd_zero_compressor : public chd_file_compressor
{
public:
// construction/destruction
chd_zero_compressor(std::uint64_t offset = 0, std::uint64_t maxoffset = 0)
: m_offset(offset)
, m_maxoffset(maxoffset)
{
}
// read interface
virtual std::uint32_t read_data(void *dest, std::uint64_t offset, std::uint32_t length) override
{
offset += m_offset;
if (offset >= m_maxoffset)
return 0;
if (offset + length > m_maxoffset)
length = m_maxoffset - offset;
std::memset(dest, 0, length);
return length;
}
private:
// internal state
std::uint64_t m_offset;
std::uint64_t m_maxoffset;
};
// ======================> chd_rawfile_compressor // ======================> chd_rawfile_compressor
class chd_rawfile_compressor : public chd_file_compressor class chd_rawfile_compressor : public chd_file_compressor
{ {
public: public:
// construction/destruction // construction/destruction
chd_rawfile_compressor(util::core_file &file, UINT64 offset = 0, UINT64 maxoffset = ~0) chd_rawfile_compressor(util::core_file &file, std::uint64_t offset = 0, std::uint64_t maxoffset = std::numeric_limits<std::uint64_t>::max())
: m_file(file), : m_file(file)
m_offset(offset), , m_offset(offset)
m_maxoffset((std::min)(maxoffset, file.size())) { } , m_maxoffset((std::min)(maxoffset, file.size()))
{
}
// read interface // read interface
virtual UINT32 read_data(void *dest, UINT64 offset, UINT32 length) virtual std::uint32_t read_data(void *dest, std::uint64_t offset, std::uint32_t length) override
{ {
offset += m_offset; offset += m_offset;
if (offset >= m_maxoffset) if (offset >= m_maxoffset)
@ -217,8 +254,8 @@ public:
private: private:
// internal state // internal state
util::core_file & m_file; util::core_file & m_file;
UINT64 m_offset; std::uint64_t m_offset;
UINT64 m_maxoffset; std::uint64_t m_maxoffset;
}; };
@ -1626,11 +1663,10 @@ static void do_create_raw(parameters_t &params)
printf("Logical size: %s\n", big_int_string(tempstr, input_end - input_start)); printf("Logical size: %s\n", big_int_string(tempstr, input_end - input_start));
// catch errors so we can close & delete the output file // catch errors so we can close & delete the output file
chd_rawfile_compressor *chd = nullptr;
try try
{ {
// create the new CHD // create the new CHD
chd = new chd_rawfile_compressor(*input_file, input_start, input_end); std::unique_ptr<chd_file_compressor> chd(new chd_rawfile_compressor(*input_file, input_start, input_end));
chd_error err; chd_error err;
if (output_parent.opened()) if (output_parent.opened())
err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent); err = chd->create(output_chd_str->c_str(), input_end - input_start, hunk_size, compression, output_parent);
@ -1645,11 +1681,9 @@ static void do_create_raw(parameters_t &params)
// compress it generically // compress it generically
compress_common(*chd); compress_common(*chd);
delete chd;
} }
catch (...) catch (...)
{ {
delete chd;
// delete the output file // delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT); auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end()) if (output_chd_str != params.end())
@ -1804,11 +1838,12 @@ static void do_create_hd(parameters_t &params)
printf("Logical size: %s\n", big_int_string(tempstr, UINT64(totalsectors) * UINT64(sector_size))); printf("Logical size: %s\n", big_int_string(tempstr, UINT64(totalsectors) * UINT64(sector_size)));
// catch errors so we can close & delete the output file // catch errors so we can close & delete the output file
chd_rawfile_compressor *chd = nullptr;
try try
{ {
// create the new hard drive // create the new hard drive
chd = new chd_rawfile_compressor(*input_file, input_start, input_end); std::unique_ptr<chd_file_compressor> chd;
if (input_file) chd.reset(new chd_rawfile_compressor(*input_file, input_start, input_end));
else chd.reset(new chd_zero_compressor(input_start, input_end));
chd_error err; chd_error err;
if (output_parent.opened()) if (output_parent.opened())
err = chd->create(output_chd_str->c_str(), UINT64(totalsectors) * UINT64(sector_size), hunk_size, compression, output_parent); err = chd->create(output_chd_str->c_str(), UINT64(totalsectors) * UINT64(sector_size), hunk_size, compression, output_parent);
@ -1834,11 +1869,9 @@ static void do_create_hd(parameters_t &params)
// compress it generically // compress it generically
if (input_file) if (input_file)
compress_common(*chd); compress_common(*chd);
delete chd;
} }
catch (...) catch (...)
{ {
delete chd;
// delete the output file // delete the output file
auto output_chd_str = params.find(OPTION_OUTPUT); auto output_chd_str = params.find(OPTION_OUTPUT);
if (output_chd_str != params.end()) if (output_chd_str != params.end())