Skip to content

Commit 6e50bee

Browse files
committed
Implement handling of other endianness in BerkeleyRODatabase
1 parent cdd61c9 commit 6e50bee

File tree

1 file changed

+69
-6
lines changed

1 file changed

+69
-6
lines changed

src/wallet/migrate.cpp

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Distributed under the MIT software license, see the accompanying
22
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
33

4+
#include <compat/byteswap.h>
45
#include <crypto/common.h> // For ReadBE32
56
#include <logging.h>
67
#include <streams.h>
@@ -94,6 +95,7 @@ class MetaPage
9495
unsigned char iv[20]; // Crypto IV
9596
unsigned char chksum[16]; // Checksum
9697

98+
bool other_endian;
9799
uint32_t expected_page_num;
98100

99101
MetaPage(uint32_t expected_page_num) : expected_page_num(expected_page_num) {}
@@ -110,6 +112,8 @@ class MetaPage
110112
s >> pagesize;
111113
s >> encrypt_algo;
112114

115+
other_endian = magic == BTREE_MAGIC_OE;
116+
113117
uint8_t uint8_type;
114118
s >> uint8_type;
115119
type = static_cast<PageType>(uint8_type);
@@ -124,6 +128,9 @@ class MetaPage
124128

125129
uint32_t uint32_flags;
126130
s >> uint32_flags;
131+
if (other_endian) {
132+
uint32_flags = internal_bswap_32(uint32_flags);
133+
}
127134
flags = static_cast<BTreeFlags>(uint32_flags);
128135

129136
s >> uid;
@@ -138,6 +145,26 @@ class MetaPage
138145
s >> iv;
139146
s >> chksum;
140147

148+
if (other_endian) {
149+
lsn_file = internal_bswap_32(lsn_file);
150+
lsn_offset = internal_bswap_32(lsn_offset);
151+
page_num = internal_bswap_32(page_num);
152+
magic = internal_bswap_32(magic);
153+
version = internal_bswap_32(version);
154+
pagesize = internal_bswap_32(pagesize);
155+
free_list = internal_bswap_32(free_list);
156+
last_page = internal_bswap_32(last_page);
157+
partitions = internal_bswap_32(partitions);
158+
key_count = internal_bswap_32(key_count);
159+
record_count = internal_bswap_32(record_count);
160+
unused2 = internal_bswap_32(unused2);
161+
minkey = internal_bswap_32(minkey);
162+
re_len = internal_bswap_32(re_len);
163+
re_pad = internal_bswap_32(re_pad);
164+
root = internal_bswap_32(root);
165+
crypto_magic = internal_bswap_32(crypto_magic);
166+
}
167+
141168
// Page number must match
142169
if (page_num != expected_page_num) {
143170
throw std::runtime_error("Meta page number mismatch");
@@ -180,6 +207,11 @@ class RecordHeader
180207

181208
static constexpr size_t SIZE = 3; // The record header is 3 bytes
182209

210+
bool other_endian;
211+
212+
RecordHeader(bool other_endian) : other_endian(other_endian) {}
213+
RecordHeader() = delete;
214+
183215
template <typename Stream>
184216
void Unserialize(Stream& s)
185217
{
@@ -189,6 +221,10 @@ class RecordHeader
189221
s >> uint8_type;
190222
type = static_cast<RecordType>(uint8_type & ~static_cast<uint8_t>(RecordType::DELETE));
191223
deleted = uint8_type & static_cast<uint8_t>(RecordType::DELETE);
224+
225+
if (other_endian) {
226+
len = internal_bswap_16(len);
227+
}
192228
}
193229
};
194230

@@ -236,6 +272,11 @@ class InternalRecord
236272

237273
data.resize(m_header.len);
238274
s.read(AsWritableBytes(Span(data.data(), data.size())));
275+
276+
if (m_header.other_endian) {
277+
page_num = internal_bswap_32(page_num);
278+
records = internal_bswap_32(records);
279+
}
239280
}
240281
};
241282

@@ -263,6 +304,11 @@ class OverflowRecord
263304
s >> unused2;
264305
s >> page_number;
265306
s >> item_len;
307+
308+
if (m_header.other_endian) {
309+
page_number = internal_bswap_32(page_number);
310+
item_len = internal_bswap_32(item_len);
311+
}
266312
}
267313
};
268314

@@ -283,8 +329,9 @@ class PageHeader
283329
static constexpr int64_t SIZE = 26; // The header is 26 bytes
284330

285331
uint32_t expected_page_num;
332+
bool other_endian;
286333

287-
PageHeader(uint32_t page_num) : expected_page_num(page_num) {}
334+
PageHeader(uint32_t page_num, bool other_endian) : expected_page_num(page_num), other_endian(other_endian) {}
288335
PageHeader() = delete;
289336

290337
template <typename Stream>
@@ -303,6 +350,16 @@ class PageHeader
303350
s >> uint8_type;
304351
type = static_cast<PageType>(uint8_type);
305352

353+
if (other_endian) {
354+
lsn_file = internal_bswap_32(lsn_file);
355+
lsn_offset = internal_bswap_32(lsn_offset);
356+
page_num = internal_bswap_32(page_num);
357+
prev_page = internal_bswap_32(prev_page);
358+
next_page = internal_bswap_32(next_page);
359+
entries = internal_bswap_16(entries);
360+
hf_offset = internal_bswap_16(hf_offset);
361+
}
362+
306363
if (expected_page_num != page_num) {
307364
throw std::runtime_error("Page number mismatch");
308365
}
@@ -335,6 +392,9 @@ class RecordsPage
335392
// Get the index
336393
uint16_t index;
337394
s >> index;
395+
if (m_header.other_endian) {
396+
index = internal_bswap_16(index);
397+
}
338398
indexes.push_back(index);
339399
pos += sizeof(uint16_t);
340400

@@ -346,7 +406,7 @@ class RecordsPage
346406
s.ignore(to_jump);
347407

348408
// Read the record
349-
RecordHeader rec_hdr;
409+
RecordHeader rec_hdr(m_header.other_endian);
350410
s >> rec_hdr;
351411
to_jump += RecordHeader::SIZE;
352412

@@ -422,6 +482,9 @@ class InternalPage
422482
// Get the index
423483
uint16_t index;
424484
s >> index;
485+
if (m_header.other_endian) {
486+
index = internal_bswap_16(index);
487+
}
425488
indexes.push_back(index);
426489
pos += sizeof(uint16_t);
427490

@@ -433,7 +496,7 @@ class InternalPage
433496
s.ignore(to_jump);
434497

435498
// Read the record
436-
RecordHeader rec_hdr;
499+
RecordHeader rec_hdr(m_header.other_endian);
437500
s >> rec_hdr;
438501
to_jump += RecordHeader::SIZE;
439502

@@ -499,7 +562,7 @@ void BerkeleyRODatabase::Open()
499562

500563
// Read the root page
501564
SeekToPage(db_file, outer_meta.root, page_size);
502-
PageHeader header(outer_meta.root);
565+
PageHeader header(outer_meta.root, outer_meta.other_endian);
503566
db_file >> header;
504567
if (header.type != PageType::BTREE_LEAF) {
505568
throw std::runtime_error("Unexpected outer database root page type");
@@ -558,7 +621,7 @@ void BerkeleyRODatabase::Open()
558621
// }
559622
pages.pop_back();
560623
SeekToPage(db_file, curr_page, page_size);
561-
PageHeader header(curr_page);
624+
PageHeader header(curr_page, inner_meta.other_endian);
562625
db_file >> header;
563626
switch (header.type) {
564627
case PageType::BTREE_INTERNAL: {
@@ -589,7 +652,7 @@ void BerkeleyRODatabase::Open()
589652
uint32_t next_page = orec->page_number;
590653
while (next_page != 0) {
591654
SeekToPage(db_file, next_page, page_size);
592-
PageHeader opage_header(next_page);
655+
PageHeader opage_header(next_page, inner_meta.other_endian);
593656
db_file >> opage_header;
594657
if (opage_header.type != PageType::OVERFLOW_DATA) {
595658
throw std::runtime_error("Bad overflow record page type");

0 commit comments

Comments
 (0)