Skip to content

Commit bc447d2

Browse files
committed
fix: destroy in the failure after partial success
1 parent c9bf1e8 commit bc447d2

1 file changed

Lines changed: 58 additions & 35 deletions

File tree

tuple/include/array_of_strings_sketch_impl.hpp

Lines changed: 58 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,39 @@ template<typename Allocator>
125125
void default_array_of_strings_serde<Allocator>::deserialize(
126126
std::istream& is, array_of_strings* items, unsigned num
127127
) const {
128-
for (unsigned i = 0; i < num; ++i) {
129-
read<uint32_t>(is); // total_bytes
130-
if (!is) throw std::runtime_error("array_of_strings stream read failed");
131-
const uint8_t num_nodes = read<uint8_t>(is);
132-
if (!is) throw std::runtime_error("array_of_strings stream read failed");
133-
check_num_nodes(num_nodes);
134-
array_of_strings array(num_nodes, "");
135-
for (uint8_t j = 0; j < num_nodes; ++j) {
136-
const uint32_t length = read<uint32_t>(is);
137-
if (!is) throw std::runtime_error("array_of_strings stream read failed");
138-
std::string value(length, '\0');
139-
if (length != 0) {
140-
is.read(&value[0], length);
141-
if (!is) throw std::runtime_error("array_of_strings stream read failed");
128+
unsigned i = 0;
129+
bool failure = false;
130+
try {
131+
for (; i < num; ++i) {
132+
read<uint32_t>(is); // total_bytes
133+
if (!is) { failure = true; break; }
134+
const uint8_t num_nodes = read<uint8_t>(is);
135+
if (!is) { failure = true; break; }
136+
check_num_nodes(num_nodes);
137+
array_of_strings array(num_nodes, "");
138+
for (uint8_t j = 0; j < num_nodes; ++j) {
139+
const uint32_t length = read<uint32_t>(is);
140+
if (!is) { failure = true; break; }
141+
std::string value(length, '\0');
142+
if (length != 0) {
143+
is.read(&value[0], length);
144+
if (!is) { failure = true; break; }
145+
}
146+
array[j] = std::move(value);
142147
}
143-
array[j] = std::move(value);
148+
if (failure) break;
149+
summary_allocator alloc(summary_allocator_);
150+
std::allocator_traits<summary_allocator>::construct(alloc, &items[i], std::move(array));
144151
}
152+
} catch (std::istream::failure&) {
153+
failure = true;
154+
}
155+
if (failure) {
145156
summary_allocator alloc(summary_allocator_);
146-
std::allocator_traits<summary_allocator>::construct(alloc, &items[i], std::move(array));
157+
for (unsigned j = 0; j < i; ++j) {
158+
std::allocator_traits<summary_allocator>::destroy(alloc, &items[j]);
159+
}
160+
throw std::runtime_error("array_of_strings stream read failed at item " + std::to_string(i));
147161
}
148162
}
149163

@@ -177,28 +191,37 @@ size_t default_array_of_strings_serde<Allocator>::deserialize(
177191
) const {
178192
const uint8_t* ptr8 = static_cast<const uint8_t*>(ptr);
179193
size_t bytes_read = 0;
180-
181-
for (unsigned i = 0; i < num; ++i) {
182-
check_memory_size(bytes_read + sizeof(uint32_t), capacity);
183-
const size_t item_start = bytes_read;
184-
uint32_t total_bytes;
185-
bytes_read += copy_from_mem(ptr8 + bytes_read, total_bytes);
186-
check_memory_size(item_start + total_bytes, capacity);
187-
uint8_t num_nodes;
188-
bytes_read += copy_from_mem(ptr8 + bytes_read, num_nodes);
189-
check_num_nodes(num_nodes);
190-
array_of_strings array(num_nodes, "");
191-
for (uint8_t j = 0; j < num_nodes; ++j) {
192-
uint32_t length;
193-
bytes_read += copy_from_mem(ptr8 + bytes_read, length);
194-
std::string value(length, '\0');
195-
if (length != 0) {
196-
bytes_read += copy_from_mem(ptr8 + bytes_read, &value[0], length);
194+
unsigned i = 0;
195+
196+
try {
197+
for (; i < num; ++i) {
198+
check_memory_size(bytes_read + sizeof(uint32_t), capacity);
199+
const size_t item_start = bytes_read;
200+
uint32_t total_bytes;
201+
bytes_read += copy_from_mem(ptr8 + bytes_read, total_bytes);
202+
check_memory_size(item_start + total_bytes, capacity);
203+
uint8_t num_nodes;
204+
bytes_read += copy_from_mem(ptr8 + bytes_read, num_nodes);
205+
check_num_nodes(num_nodes);
206+
array_of_strings array(num_nodes, "");
207+
for (uint8_t j = 0; j < num_nodes; ++j) {
208+
uint32_t length;
209+
bytes_read += copy_from_mem(ptr8 + bytes_read, length);
210+
std::string value(length, '\0');
211+
if (length != 0) {
212+
bytes_read += copy_from_mem(ptr8 + bytes_read, &value[0], length);
213+
}
214+
array[j] = std::move(value);
197215
}
198-
array[j] = std::move(value);
216+
summary_allocator alloc(summary_allocator_);
217+
std::allocator_traits<summary_allocator>::construct(alloc, &items[i], std::move(array));
199218
}
219+
} catch (...) {
200220
summary_allocator alloc(summary_allocator_);
201-
std::allocator_traits<summary_allocator>::construct(alloc, &items[i], std::move(array));
221+
for (unsigned j = 0; j < i; ++j) {
222+
std::allocator_traits<summary_allocator>::destroy(alloc, &items[j]);
223+
}
224+
throw;
202225
}
203226
return bytes_read;
204227
}

0 commit comments

Comments
 (0)