From 5ab8fd3d87cc5b36af93da774d26abb0762a1016 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Mon, 7 Mar 2011 23:39:52 +0000 Subject: [PATCH] add no-throwing validation code. git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@376 aa027e90-d47c-11dd-86d7-074df07e0730 --- Device/DavexDiskImage.cpp | 68 +++++++++++++++++--------------- Device/DavexDiskImage.h | 6 ++- Device/DiskImage.cpp | 47 ++++++++++++++++++---- Device/DiskImage.h | 11 ++++-- Device/SDKImage.cpp | 73 +++++++++++++++-------------------- Device/SDKImage.h | 3 ++ Device/UniversalDiskImage.cpp | 55 ++++++++++++++------------ Device/UniversalDiskImage.h | 5 ++- 8 files changed, 156 insertions(+), 112 deletions(-) diff --git a/Device/DavexDiskImage.cpp b/Device/DavexDiskImage.cpp index 51270bc..f9e44ab 100644 --- a/Device/DavexDiskImage.cpp +++ b/Device/DavexDiskImage.cpp @@ -47,42 +47,48 @@ DavexDiskImage::~DavexDiskImage() // scan and update usedBlocks? } -void DavexDiskImage::Validate(MappedFile *f) +bool DavexDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "DavexDiskImage::Validate" + + size_t size = f->length(); + const void * data = f->address(); + unsigned blocks = (size / 512) - 1; + + + if (size < 512) return false; + if (size % 512) return false; + + // identity. + if (std::memcmp(data, IdentityCheck, 16)) + return false; + + // file format. + if (Read8(data, 0x10) != 0) + return false; + + // total blocks + if (Read32(data, 33) != blocks) + return false; + + // file number -- must be 1 + if (Read8(data, 64) != 1) + return false; + + return true; +} + +bool DavexDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "DavexDiskImage::Validate" - size_t size = f->length(); - const void * data = f->address(); - bool ok = false; - unsigned blocks = (size / 512) - 1; - - do { - if (size < 512) break; - if (size % 512) break; - - // identity. - if (std::memcmp(data, IdentityCheck, 16)) - break; - - // file format. - if (Read8(data, 0x10) != 0) - break; - - // total blocks - if (Read32(data, 33) != blocks) - break; - - // file number -- must be 1 - if (Read8(data, 64) != 1) - break; - - ok = true; - } while (false); - - - if (!ok) + + if (!Validate(f, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); + + return true; } BlockDevicePointer DavexDiskImage::Open(MappedFile *file) diff --git a/Device/DavexDiskImage.h b/Device/DavexDiskImage.h index b7a3d36..0c25f04 100644 --- a/Device/DavexDiskImage.h +++ b/Device/DavexDiskImage.h @@ -2,6 +2,7 @@ #define __DAVEXDISKIMAGE_H__ #include +#include #include #include @@ -22,12 +23,15 @@ public: virtual BlockCachePointer createBlockCache(); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: DavexDiskImage(); DavexDiskImage(MappedFile *); - static void Validate(MappedFile *); + bool _changed; std::string _volumeName; diff --git a/Device/DiskImage.cpp b/Device/DiskImage.cpp index 6025e5d..2450ccb 100644 --- a/Device/DiskImage.cpp +++ b/Device/DiskImage.cpp @@ -126,18 +126,33 @@ BlockDevicePointer ProDOSOrderDiskImage::Open(MappedFile *file) return MAKE_SHARED(ProDOSOrderDiskImage, file); } -void ProDOSOrderDiskImage::Validate(MappedFile *f) + +bool ProDOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "ProDOSOrderDiskImage::Validate" + + + size_t size = f->length(); + + if (size % 512) + return false; + + return true; + +} + +bool ProDOSOrderDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "ProDOSOrderDiskImage::Validate" if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - - size_t size = f->length(); - - if (size % 512) + + if (!Validate(f)) throw Exception(__METHOD__ ": Invalid file format."); + return true; } BlockCachePointer ProDOSOrderDiskImage::createBlockCache() @@ -157,6 +172,8 @@ DOSOrderDiskImage::DOSOrderDiskImage(const char *name, bool readOnly) : } */ + + DOSOrderDiskImage::DOSOrderDiskImage(MappedFile *file) : DiskImage(file) { @@ -182,16 +199,30 @@ BlockDevicePointer DOSOrderDiskImage::Open(MappedFile *file) } -void DOSOrderDiskImage::Validate(MappedFile *f) +bool DOSOrderDiskImage::Validate(MappedFile *f, const std::nothrow_t &) +{ +#undef __METHOD__ +#define __METHOD__ "DOSOrderDiskImage::Validate" + + size_t size = f->length(); + + if (size % 512) + return false; + + return true; + +} + +bool DOSOrderDiskImage::Validate(MappedFile *f) { #undef __METHOD__ #define __METHOD__ "DOSOrderDiskImage::Validate" if (!f || !f->isValid()) throw Exception(__METHOD__ ": File not set."); - size_t size = f->length(); - if (size % 512) + if (!Validate(f)) throw Exception(__METHOD__ ": Invalid file format."); + return true; } diff --git a/Device/DiskImage.h b/Device/DiskImage.h index 35034f5..25a5c39 100644 --- a/Device/DiskImage.h +++ b/Device/DiskImage.h @@ -62,13 +62,14 @@ public: virtual BlockCachePointer createBlockCache(); - + + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: ProDOSOrderDiskImage(); - ProDOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); }; class DOSOrderDiskImage : public DiskImage { @@ -78,11 +79,13 @@ public: static BlockDevicePointer Create(const char *name, size_t blocks); static BlockDevicePointer Open(MappedFile *); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: DOSOrderDiskImage(); DOSOrderDiskImage(MappedFile *); - static void Validate(MappedFile *); }; diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp index 9a569b9..eb62279 100644 --- a/Device/SDKImage.cpp +++ b/Device/SDKImage.cpp @@ -62,48 +62,6 @@ struct record_thread NuThreadIdx thread_index; }; -/* - * callback function to scan contents. - * (not used). - * - */ -static NuResult ContentFunction(NuArchive *archive, void *vp) -{ - const NuRecord *record = (const NuRecord *)vp; - - /* - * The application must not attempt to retain a copy of "pRecord" - * after the callback returns, as the structure may be freed. - * Anything of interest should be copied out. - */ - - - for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i) - { - const NuThread *thread = NuGetThread(record, i); - - - printf("%ld, %ld\n", (long)record->recordIdx, (long)thread->threadIdx); - - if (NuGetThreadID(thread) == kNuThreadIDDiskImage) - { - record_thread *rt; - - NuGetExtraData(archive, (void **)&rt); - if (rt) - { - rt->record_index = record->recordIdx; - rt->thread_index = thread->threadIdx; - } - - return kNuAbort; - } - - } - - - return kNuOK; -} static record_thread FindDiskImageThread(NuArchive *archive) { @@ -245,3 +203,34 @@ BlockDevicePointer SDKImage::Open(const char *name) return ProDOSOrderDiskImage::Open(&file); } + + + +bool SDKImage::Validate(MappedFile * f, const std::nothrow_t &) +{ + // NuFile, alternating ASCII. + static const char IdentityCheck[6] = { 0x4E, 0xF5, 0x46, 0xE9, 0x6C, 0xE5 }; + + if (f->length() < sizeof(IdentityCheck)) + return false; + + if (std::memcmp(f->address(), IdentityCheck, sizeof(IdentityCheck))) + return false; + + return true; + +} + +bool SDKImage::Validate(MappedFile * f) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::Validate" + + if (!Validate(f)) + throw Exception(__METHOD__ ": Invalid file format."); + + return true; +} + + + diff --git a/Device/SDKImage.h b/Device/SDKImage.h index 4d54444..fb51fd2 100644 --- a/Device/SDKImage.h +++ b/Device/SDKImage.h @@ -18,6 +18,9 @@ namespace Device { static BlockDevicePointer Open(const char *name); + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: SDKImage(); SDKImage(const SDKImage &); diff --git a/Device/UniversalDiskImage.cpp b/Device/UniversalDiskImage.cpp index 96ad4ef..18cec76 100644 --- a/Device/UniversalDiskImage.cpp +++ b/Device/UniversalDiskImage.cpp @@ -100,42 +100,47 @@ BlockDevicePointer UniversalDiskImage::Open(MappedFile *file) * TODO -- honor read-only flag. * */ -void UniversalDiskImage::Validate(MappedFile *file) + +bool UniversalDiskImage::Validate(MappedFile *file, const std::nothrow_t &) { #undef __METHOD__ #define __METHOD__ "UniversalDiskImage::Validate" - + const void *data = file->address(); size_t size = file->length(); - bool ok = false; + unsigned blocks = 0; unsigned offset = 0; - do { - - if (size < 64) break; - - if (std::memcmp(data, "2IMG", 4)) break; - - // only prodos supported, for now... - // TODO -- Dos Order, Nibble support. - if (Read32(data, 0x0c) != 1) break; - - blocks = Read32(data, 0x14); - offset = Read32(data, 0x18); - - // file size == blocks * 512 - if (Read32(data, 0x1c) != blocks * 512) break; - - if (offset + blocks * 512 > size) break; - - ok = true; - } while (false); + + if (size < 64) return false; - if (!ok) + if (std::memcmp(data, "2IMG", 4)) return false; + + // only prodos supported, for now... + // TODO -- Dos Order, Nibble support. + if (Read32(data, 0x0c) != 1) return false; + + blocks = Read32(data, 0x14); + offset = Read32(data, 0x18); + + // file size == blocks * 512 + if (Read32(data, 0x1c) != blocks * 512) return false; + + if (offset + blocks * 512 > size) return false; + + return true; +} + +bool UniversalDiskImage::Validate(MappedFile *file) +{ +#undef __METHOD__ +#define __METHOD__ "UniversalDiskImage::Validate" + + if (!Validate(file, std::nothrow)) throw Exception(__METHOD__ ": Invalid file format."); - + return true; } diff --git a/Device/UniversalDiskImage.h b/Device/UniversalDiskImage.h index 23b5b9d..fc54026 100644 --- a/Device/UniversalDiskImage.h +++ b/Device/UniversalDiskImage.h @@ -21,13 +21,16 @@ public: virtual BlockCachePointer createBlockCache(); + + static bool Validate(MappedFile *, const std::nothrow_t &); + static bool Validate(MappedFile *); + private: UniversalDiskImage(); UniversalDiskImage(MappedFile *); - static void Validate(MappedFile *); uint32_t _format; uint32_t _flags;