Kaydet (Commit) e7da3822 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

Check for recursive maps

Change-Id: I50227c41c5b4c5c410939ddfa078b996b5804965
üst b0583c57
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <set>
#include <vector> #include <vector>
#include "osl/endian.h" #include "osl/endian.h"
...@@ -364,6 +365,11 @@ struct MapEntry { ...@@ -364,6 +365,11 @@ struct MapEntry {
Memory32 data; Memory32 data;
}; };
bool operator <(Map const map1, Map const map2) {
return map1.begin < map2.begin
|| (map1.begin == map2.begin && map1.size < map2.size);
}
namespace { namespace {
enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL }; enum Compare { COMPARE_LESS, COMPARE_GREATER, COMPARE_EQUAL };
...@@ -543,14 +549,20 @@ ConstantValue readConstant( ...@@ -543,14 +549,20 @@ ConstantValue readConstant(
} }
rtl::Reference< Entity > readEntity( rtl::Reference< Entity > readEntity(
rtl::Reference< MappedFile > const & file, sal_uInt32 offset); rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
std::set<Map> const & trace);
class UnoidlModuleEntity;
class UnoidlCursor: public MapCursor { class UnoidlCursor: public MapCursor {
public: public:
UnoidlCursor( UnoidlCursor(
rtl::Reference< MappedFile > file, MapEntry const * mapBegin, rtl::Reference< MappedFile > file,
sal_uInt32 mapSize): rtl::Reference<UnoidlProvider> const & reference1,
file_(file), mapIndex_(mapBegin), mapEnd_(mapBegin + mapSize) rtl::Reference<UnoidlModuleEntity> const & reference2,
NestedMap const & map):
file_(file), reference1_(reference1), reference2_(reference2),
map_(map), index_(0)
{} {}
private: private:
...@@ -559,17 +571,20 @@ private: ...@@ -559,17 +571,20 @@ private:
virtual rtl::Reference< Entity > getNext(OUString * name) SAL_OVERRIDE; virtual rtl::Reference< Entity > getNext(OUString * name) SAL_OVERRIDE;
rtl::Reference< MappedFile > file_; rtl::Reference< MappedFile > file_;
MapEntry const * mapIndex_; rtl::Reference<UnoidlProvider> reference1_; // HACK to keep alive whatever
MapEntry const * mapEnd_; rtl::Reference<UnoidlModuleEntity> reference2_; // owner of map_
NestedMap const & map_;
sal_uInt32 index_;
}; };
rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) { rtl::Reference< Entity > UnoidlCursor::getNext(OUString * name) {
assert(name != 0); assert(name != 0);
rtl::Reference< Entity > ent; rtl::Reference< Entity > ent;
if (mapIndex_ != mapEnd_) { if (index_ != map_.map.size) {
*name = file_->readNulName(mapIndex_->name.getUnsigned32()); *name = file_->readNulName(map_.map.begin[index_].name.getUnsigned32());
ent = readEntity(file_, mapIndex_->data.getUnsigned32()); ent = readEntity(
++mapIndex_; file_, map_.map.begin[index_].data.getUnsigned32(), map_.trace);
++index_;
} }
return ent; return ent;
} }
...@@ -578,37 +593,47 @@ class UnoidlModuleEntity: public ModuleEntity { ...@@ -578,37 +593,47 @@ class UnoidlModuleEntity: public ModuleEntity {
public: public:
UnoidlModuleEntity( UnoidlModuleEntity(
rtl::Reference< MappedFile > const & file, sal_uInt32 mapOffset, rtl::Reference< MappedFile > const & file, sal_uInt32 mapOffset,
sal_uInt32 mapSize): sal_uInt32 mapSize, std::set<Map> const & trace):
file_(file), file_(file)
mapBegin_( {
reinterpret_cast< MapEntry const * >( assert(file.is());
static_cast< char const * >(file_->address) + mapOffset)), map_.map.begin = reinterpret_cast<MapEntry const *>(
mapSize_(mapSize) static_cast<char const *>(file_->address) + mapOffset);
{ assert(file.is()); } map_.map.size = mapSize;
map_.trace = trace;
if (!map_.trace.insert(map_.map).second) {
throw FileFormatException(
file_->uri, "UNOIDL format: recursive map");
}
}
private: private:
virtual ~UnoidlModuleEntity() throw () {} virtual ~UnoidlModuleEntity() throw () {}
virtual std::vector< OUString > getMemberNames() const SAL_OVERRIDE; virtual std::vector< OUString > getMemberNames() const SAL_OVERRIDE;
virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE virtual rtl::Reference< MapCursor > createCursor() const SAL_OVERRIDE {
{ return new UnoidlCursor(file_, mapBegin_, mapSize_); } return new UnoidlCursor(
file_, rtl::Reference<UnoidlProvider>(),
const_cast<UnoidlModuleEntity *>(this), map_);
}
rtl::Reference< MappedFile > file_; rtl::Reference< MappedFile > file_;
MapEntry const * mapBegin_; NestedMap map_;
sal_uInt32 mapSize_;
}; };
std::vector< OUString > UnoidlModuleEntity::getMemberNames() const { std::vector< OUString > UnoidlModuleEntity::getMemberNames() const {
std::vector< OUString > names; std::vector< OUString > names;
for (sal_uInt32 i = 0; i != mapSize_; ++i) { for (sal_uInt32 i = 0; i != map_.map.size; ++i) {
names.push_back(file_->readNulName(mapBegin_[i].name.getUnsigned32())); names.push_back(
file_->readNulName(map_.map.begin[i].name.getUnsigned32()));
} }
return names; return names;
} }
rtl::Reference< Entity > readEntity( rtl::Reference< Entity > readEntity(
rtl::Reference< MappedFile > const & file, sal_uInt32 offset) rtl::Reference< MappedFile > const & file, sal_uInt32 offset,
std::set<Map> const & trace)
{ {
assert(file.is()); assert(file.is());
int v = file->read8(offset); int v = file->read8(offset);
...@@ -637,7 +662,7 @@ rtl::Reference< Entity > readEntity( ...@@ -637,7 +662,7 @@ rtl::Reference< Entity > readEntity(
file->uri, file->uri,
"UNOIDL format: module map offset + size too large"); "UNOIDL format: module map offset + size too large");
} }
return new UnoidlModuleEntity(file, offset + 5, n); return new UnoidlModuleEntity(file, offset + 5, n, trace);
} }
case 1: // enum type case 1: // enum type
{ {
...@@ -1193,35 +1218,40 @@ UnoidlProvider::UnoidlProvider(OUString const & uri): file_(new MappedFile(uri)) ...@@ -1193,35 +1218,40 @@ UnoidlProvider::UnoidlProvider(OUString const & uri): file_(new MappedFile(uri))
" 0"); " 0");
} }
sal_uInt32 off = file_->read32(8); sal_uInt32 off = file_->read32(8);
mapSize_ = file_->read32(12); map_.map.size = file_->read32(12);
if (off + 8 * sal_uInt64(mapSize_) > file_->size) { // cannot overflow if (off + 8 * sal_uInt64(map_.map.size) > file_->size) { // cannot overflow
throw FileFormatException( throw FileFormatException(
file_->uri, "UNOIDL format: root map offset + size too large"); file_->uri, "UNOIDL format: root map offset + size too large");
} }
mapBegin_ = reinterpret_cast< MapEntry const * >( map_.map.begin = reinterpret_cast< MapEntry const * >(
static_cast< char const * >(file_->address) + off); static_cast< char const * >(file_->address) + off);
map_.trace.insert(map_.map);
} }
rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const { rtl::Reference< MapCursor > UnoidlProvider::createRootCursor() const {
return new UnoidlCursor(file_, mapBegin_, mapSize_); return new UnoidlCursor(
file_, const_cast<UnoidlProvider *>(this),
rtl::Reference<UnoidlModuleEntity>(), map_);
} }
rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const
{ {
MapEntry const * mapBegin = mapBegin_; NestedMap map(map_);
sal_uInt32 mapSize = mapSize_;
bool cgroup = false; bool cgroup = false;
for (sal_Int32 i = 0;;) { for (sal_Int32 i = 0;;) {
sal_Int32 j = name.indexOf('.', i); sal_Int32 j = name.indexOf('.', i);
if (j == -1) { if (j == -1) {
j = name.getLength(); j = name.getLength();
} }
sal_Int32 off = findInMap(file_, mapBegin, mapSize, name, i, j - i); sal_Int32 off = findInMap(
file_, map.map.begin, map.map.size, name, i, j - i);
if (off == 0) { if (off == 0) {
return rtl::Reference< Entity >(); return rtl::Reference< Entity >();
} }
if (j == name.getLength()) { if (j == name.getLength()) {
return cgroup ? rtl::Reference< Entity >() : readEntity(file_, off); return cgroup
? rtl::Reference< Entity >()
: readEntity(file_, off, map.trace);
} }
if (cgroup) { if (cgroup) {
return rtl::Reference< Entity >(); return rtl::Reference< Entity >();
...@@ -1240,15 +1270,19 @@ rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const ...@@ -1240,15 +1270,19 @@ rtl::Reference< Entity > UnoidlProvider::findEntity(OUString const & name) const
// prefix of the requested name's segments? // prefix of the requested name's segments?
} }
} }
mapSize = file_->read32(off + 1); map.map.size = file_->read32(off + 1);
if (sal_uInt64(off) + 5 + 8 * sal_uInt64(mapSize) > file_->size) if (sal_uInt64(off) + 5 + 8 * sal_uInt64(map.map.size) > file_->size)
// cannot overflow // cannot overflow
{ {
throw FileFormatException( throw FileFormatException(
file_->uri, "UNOIDL format: map offset + size too large"); file_->uri, "UNOIDL format: map offset + size too large");
} }
mapBegin = reinterpret_cast< MapEntry const * >( map.map.begin = reinterpret_cast< MapEntry const * >(
static_cast< char const * >(file_->address) + off + 5); static_cast< char const * >(file_->address) + off + 5);
if (!map.trace.insert(map.map).second) {
throw FileFormatException(
file_->uri, "UNOIDL format: recursive map");
}
i = j + 1; i = j + 1;
} }
} }
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include "sal/config.h" #include "sal/config.h"
#include <set>
#include "rtl/ref.hxx" #include "rtl/ref.hxx"
#include "sal/types.h" #include "sal/types.h"
#include "unoidl/unoidl.hxx" #include "unoidl/unoidl.hxx"
...@@ -21,6 +23,16 @@ namespace unoidl { namespace detail { ...@@ -21,6 +23,16 @@ namespace unoidl { namespace detail {
class MappedFile; class MappedFile;
struct MapEntry; struct MapEntry;
struct Map {
MapEntry const * begin;
sal_uInt32 size;
};
struct NestedMap {
Map map;
std::set<Map> trace;
};
class UnoidlProvider: public Provider { class UnoidlProvider: public Provider {
public: public:
// throws FileFormatException, NoSuchFileException: // throws FileFormatException, NoSuchFileException:
...@@ -37,8 +49,7 @@ private: ...@@ -37,8 +49,7 @@ private:
virtual ~UnoidlProvider() throw (); virtual ~UnoidlProvider() throw ();
rtl::Reference< detail::MappedFile > file_; rtl::Reference< detail::MappedFile > file_;
detail::MapEntry const * mapBegin_; NestedMap map_;
sal_uInt32 mapSize_;
}; };
} } } }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment