mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
Implement handling of other endianness in BerkeleyRODatabase
This commit is contained in:
parent
cdd61c9cc1
commit
6e50bee67d
1 changed files with 69 additions and 6 deletions
|
@ -1,6 +1,7 @@
|
||||||
// Distributed under the MIT software license, see the accompanying
|
// Distributed under the MIT software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <compat/byteswap.h>
|
||||||
#include <crypto/common.h> // For ReadBE32
|
#include <crypto/common.h> // For ReadBE32
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
#include <streams.h>
|
#include <streams.h>
|
||||||
|
@ -94,6 +95,7 @@ public:
|
||||||
unsigned char iv[20]; // Crypto IV
|
unsigned char iv[20]; // Crypto IV
|
||||||
unsigned char chksum[16]; // Checksum
|
unsigned char chksum[16]; // Checksum
|
||||||
|
|
||||||
|
bool other_endian;
|
||||||
uint32_t expected_page_num;
|
uint32_t expected_page_num;
|
||||||
|
|
||||||
MetaPage(uint32_t expected_page_num) : expected_page_num(expected_page_num) {}
|
MetaPage(uint32_t expected_page_num) : expected_page_num(expected_page_num) {}
|
||||||
|
@ -110,6 +112,8 @@ public:
|
||||||
s >> pagesize;
|
s >> pagesize;
|
||||||
s >> encrypt_algo;
|
s >> encrypt_algo;
|
||||||
|
|
||||||
|
other_endian = magic == BTREE_MAGIC_OE;
|
||||||
|
|
||||||
uint8_t uint8_type;
|
uint8_t uint8_type;
|
||||||
s >> uint8_type;
|
s >> uint8_type;
|
||||||
type = static_cast<PageType>(uint8_type);
|
type = static_cast<PageType>(uint8_type);
|
||||||
|
@ -124,6 +128,9 @@ public:
|
||||||
|
|
||||||
uint32_t uint32_flags;
|
uint32_t uint32_flags;
|
||||||
s >> uint32_flags;
|
s >> uint32_flags;
|
||||||
|
if (other_endian) {
|
||||||
|
uint32_flags = internal_bswap_32(uint32_flags);
|
||||||
|
}
|
||||||
flags = static_cast<BTreeFlags>(uint32_flags);
|
flags = static_cast<BTreeFlags>(uint32_flags);
|
||||||
|
|
||||||
s >> uid;
|
s >> uid;
|
||||||
|
@ -138,6 +145,26 @@ public:
|
||||||
s >> iv;
|
s >> iv;
|
||||||
s >> chksum;
|
s >> chksum;
|
||||||
|
|
||||||
|
if (other_endian) {
|
||||||
|
lsn_file = internal_bswap_32(lsn_file);
|
||||||
|
lsn_offset = internal_bswap_32(lsn_offset);
|
||||||
|
page_num = internal_bswap_32(page_num);
|
||||||
|
magic = internal_bswap_32(magic);
|
||||||
|
version = internal_bswap_32(version);
|
||||||
|
pagesize = internal_bswap_32(pagesize);
|
||||||
|
free_list = internal_bswap_32(free_list);
|
||||||
|
last_page = internal_bswap_32(last_page);
|
||||||
|
partitions = internal_bswap_32(partitions);
|
||||||
|
key_count = internal_bswap_32(key_count);
|
||||||
|
record_count = internal_bswap_32(record_count);
|
||||||
|
unused2 = internal_bswap_32(unused2);
|
||||||
|
minkey = internal_bswap_32(minkey);
|
||||||
|
re_len = internal_bswap_32(re_len);
|
||||||
|
re_pad = internal_bswap_32(re_pad);
|
||||||
|
root = internal_bswap_32(root);
|
||||||
|
crypto_magic = internal_bswap_32(crypto_magic);
|
||||||
|
}
|
||||||
|
|
||||||
// Page number must match
|
// Page number must match
|
||||||
if (page_num != expected_page_num) {
|
if (page_num != expected_page_num) {
|
||||||
throw std::runtime_error("Meta page number mismatch");
|
throw std::runtime_error("Meta page number mismatch");
|
||||||
|
@ -180,6 +207,11 @@ public:
|
||||||
|
|
||||||
static constexpr size_t SIZE = 3; // The record header is 3 bytes
|
static constexpr size_t SIZE = 3; // The record header is 3 bytes
|
||||||
|
|
||||||
|
bool other_endian;
|
||||||
|
|
||||||
|
RecordHeader(bool other_endian) : other_endian(other_endian) {}
|
||||||
|
RecordHeader() = delete;
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
void Unserialize(Stream& s)
|
void Unserialize(Stream& s)
|
||||||
{
|
{
|
||||||
|
@ -189,6 +221,10 @@ public:
|
||||||
s >> uint8_type;
|
s >> uint8_type;
|
||||||
type = static_cast<RecordType>(uint8_type & ~static_cast<uint8_t>(RecordType::DELETE));
|
type = static_cast<RecordType>(uint8_type & ~static_cast<uint8_t>(RecordType::DELETE));
|
||||||
deleted = uint8_type & static_cast<uint8_t>(RecordType::DELETE);
|
deleted = uint8_type & static_cast<uint8_t>(RecordType::DELETE);
|
||||||
|
|
||||||
|
if (other_endian) {
|
||||||
|
len = internal_bswap_16(len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -236,6 +272,11 @@ public:
|
||||||
|
|
||||||
data.resize(m_header.len);
|
data.resize(m_header.len);
|
||||||
s.read(AsWritableBytes(Span(data.data(), data.size())));
|
s.read(AsWritableBytes(Span(data.data(), data.size())));
|
||||||
|
|
||||||
|
if (m_header.other_endian) {
|
||||||
|
page_num = internal_bswap_32(page_num);
|
||||||
|
records = internal_bswap_32(records);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -263,6 +304,11 @@ public:
|
||||||
s >> unused2;
|
s >> unused2;
|
||||||
s >> page_number;
|
s >> page_number;
|
||||||
s >> item_len;
|
s >> item_len;
|
||||||
|
|
||||||
|
if (m_header.other_endian) {
|
||||||
|
page_number = internal_bswap_32(page_number);
|
||||||
|
item_len = internal_bswap_32(item_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,8 +329,9 @@ public:
|
||||||
static constexpr int64_t SIZE = 26; // The header is 26 bytes
|
static constexpr int64_t SIZE = 26; // The header is 26 bytes
|
||||||
|
|
||||||
uint32_t expected_page_num;
|
uint32_t expected_page_num;
|
||||||
|
bool other_endian;
|
||||||
|
|
||||||
PageHeader(uint32_t page_num) : expected_page_num(page_num) {}
|
PageHeader(uint32_t page_num, bool other_endian) : expected_page_num(page_num), other_endian(other_endian) {}
|
||||||
PageHeader() = delete;
|
PageHeader() = delete;
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
|
@ -303,6 +350,16 @@ public:
|
||||||
s >> uint8_type;
|
s >> uint8_type;
|
||||||
type = static_cast<PageType>(uint8_type);
|
type = static_cast<PageType>(uint8_type);
|
||||||
|
|
||||||
|
if (other_endian) {
|
||||||
|
lsn_file = internal_bswap_32(lsn_file);
|
||||||
|
lsn_offset = internal_bswap_32(lsn_offset);
|
||||||
|
page_num = internal_bswap_32(page_num);
|
||||||
|
prev_page = internal_bswap_32(prev_page);
|
||||||
|
next_page = internal_bswap_32(next_page);
|
||||||
|
entries = internal_bswap_16(entries);
|
||||||
|
hf_offset = internal_bswap_16(hf_offset);
|
||||||
|
}
|
||||||
|
|
||||||
if (expected_page_num != page_num) {
|
if (expected_page_num != page_num) {
|
||||||
throw std::runtime_error("Page number mismatch");
|
throw std::runtime_error("Page number mismatch");
|
||||||
}
|
}
|
||||||
|
@ -335,6 +392,9 @@ public:
|
||||||
// Get the index
|
// Get the index
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
s >> index;
|
s >> index;
|
||||||
|
if (m_header.other_endian) {
|
||||||
|
index = internal_bswap_16(index);
|
||||||
|
}
|
||||||
indexes.push_back(index);
|
indexes.push_back(index);
|
||||||
pos += sizeof(uint16_t);
|
pos += sizeof(uint16_t);
|
||||||
|
|
||||||
|
@ -346,7 +406,7 @@ public:
|
||||||
s.ignore(to_jump);
|
s.ignore(to_jump);
|
||||||
|
|
||||||
// Read the record
|
// Read the record
|
||||||
RecordHeader rec_hdr;
|
RecordHeader rec_hdr(m_header.other_endian);
|
||||||
s >> rec_hdr;
|
s >> rec_hdr;
|
||||||
to_jump += RecordHeader::SIZE;
|
to_jump += RecordHeader::SIZE;
|
||||||
|
|
||||||
|
@ -422,6 +482,9 @@ public:
|
||||||
// Get the index
|
// Get the index
|
||||||
uint16_t index;
|
uint16_t index;
|
||||||
s >> index;
|
s >> index;
|
||||||
|
if (m_header.other_endian) {
|
||||||
|
index = internal_bswap_16(index);
|
||||||
|
}
|
||||||
indexes.push_back(index);
|
indexes.push_back(index);
|
||||||
pos += sizeof(uint16_t);
|
pos += sizeof(uint16_t);
|
||||||
|
|
||||||
|
@ -433,7 +496,7 @@ public:
|
||||||
s.ignore(to_jump);
|
s.ignore(to_jump);
|
||||||
|
|
||||||
// Read the record
|
// Read the record
|
||||||
RecordHeader rec_hdr;
|
RecordHeader rec_hdr(m_header.other_endian);
|
||||||
s >> rec_hdr;
|
s >> rec_hdr;
|
||||||
to_jump += RecordHeader::SIZE;
|
to_jump += RecordHeader::SIZE;
|
||||||
|
|
||||||
|
@ -499,7 +562,7 @@ void BerkeleyRODatabase::Open()
|
||||||
|
|
||||||
// Read the root page
|
// Read the root page
|
||||||
SeekToPage(db_file, outer_meta.root, page_size);
|
SeekToPage(db_file, outer_meta.root, page_size);
|
||||||
PageHeader header(outer_meta.root);
|
PageHeader header(outer_meta.root, outer_meta.other_endian);
|
||||||
db_file >> header;
|
db_file >> header;
|
||||||
if (header.type != PageType::BTREE_LEAF) {
|
if (header.type != PageType::BTREE_LEAF) {
|
||||||
throw std::runtime_error("Unexpected outer database root page type");
|
throw std::runtime_error("Unexpected outer database root page type");
|
||||||
|
@ -558,7 +621,7 @@ void BerkeleyRODatabase::Open()
|
||||||
// }
|
// }
|
||||||
pages.pop_back();
|
pages.pop_back();
|
||||||
SeekToPage(db_file, curr_page, page_size);
|
SeekToPage(db_file, curr_page, page_size);
|
||||||
PageHeader header(curr_page);
|
PageHeader header(curr_page, inner_meta.other_endian);
|
||||||
db_file >> header;
|
db_file >> header;
|
||||||
switch (header.type) {
|
switch (header.type) {
|
||||||
case PageType::BTREE_INTERNAL: {
|
case PageType::BTREE_INTERNAL: {
|
||||||
|
@ -589,7 +652,7 @@ void BerkeleyRODatabase::Open()
|
||||||
uint32_t next_page = orec->page_number;
|
uint32_t next_page = orec->page_number;
|
||||||
while (next_page != 0) {
|
while (next_page != 0) {
|
||||||
SeekToPage(db_file, next_page, page_size);
|
SeekToPage(db_file, next_page, page_size);
|
||||||
PageHeader opage_header(next_page);
|
PageHeader opage_header(next_page, inner_meta.other_endian);
|
||||||
db_file >> opage_header;
|
db_file >> opage_header;
|
||||||
if (opage_header.type != PageType::OVERFLOW_DATA) {
|
if (opage_header.type != PageType::OVERFLOW_DATA) {
|
||||||
throw std::runtime_error("Bad overflow record page type");
|
throw std::runtime_error("Bad overflow record page type");
|
||||||
|
|
Loading…
Add table
Reference in a new issue