mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
Introduce copy_bytes for writing into bytecode
Protects memcpy from nullptr sources, which triggers failures in GCC's UB sanitizer.
This commit is contained in:
parent
cf3ddd9e88
commit
2a2576e907
@ -1136,16 +1136,11 @@ aligned_unique_ptr<NFA> goughCompile(raw_som_dfa &raw, u8 somPrecision,
|
|||||||
gough_dfa->length = gough_size;
|
gough_dfa->length = gough_size;
|
||||||
|
|
||||||
/* copy in blocks */
|
/* copy in blocks */
|
||||||
memcpy((u8 *)gough_dfa.get() + edge_prog_offset, &edge_blocks[0],
|
copy_bytes((u8 *)gough_dfa.get() + edge_prog_offset, edge_blocks);
|
||||||
byte_length(edge_blocks));
|
|
||||||
if (top_prog_offset) {
|
if (top_prog_offset) {
|
||||||
memcpy((u8 *)gough_dfa.get() + top_prog_offset, &top_blocks[0],
|
copy_bytes((u8 *)gough_dfa.get() + top_prog_offset, top_blocks);
|
||||||
byte_length(top_blocks));
|
|
||||||
}
|
|
||||||
if (!temp_blocks.empty()) {
|
|
||||||
memcpy((u8 *)gough_dfa.get() + prog_base_offset, &temp_blocks[0],
|
|
||||||
byte_length(temp_blocks));
|
|
||||||
}
|
}
|
||||||
|
copy_bytes((u8 *)gough_dfa.get() + prog_base_offset, temp_blocks);
|
||||||
|
|
||||||
return gough_dfa;
|
return gough_dfa;
|
||||||
}
|
}
|
||||||
|
@ -1397,8 +1397,7 @@ struct Factory {
|
|||||||
repeat->horizon = rsi.horizon;
|
repeat->horizon = rsi.horizon;
|
||||||
repeat->packedCtrlSize = rsi.packedCtrlSize;
|
repeat->packedCtrlSize = rsi.packedCtrlSize;
|
||||||
repeat->stateSize = rsi.stateSize;
|
repeat->stateSize = rsi.stateSize;
|
||||||
memcpy(repeat->packedFieldSizes, rsi.packedFieldSizes.data(),
|
copy_bytes(repeat->packedFieldSizes, rsi.packedFieldSizes);
|
||||||
byte_length(rsi.packedFieldSizes));
|
|
||||||
repeat->patchCount = rsi.patchCount;
|
repeat->patchCount = rsi.patchCount;
|
||||||
repeat->patchSize = rsi.patchSize;
|
repeat->patchSize = rsi.patchSize;
|
||||||
repeat->encodingSize = rsi.encodingSize;
|
repeat->encodingSize = rsi.encodingSize;
|
||||||
@ -1413,8 +1412,7 @@ struct Factory {
|
|||||||
// Copy in the sparse lookup table.
|
// Copy in the sparse lookup table.
|
||||||
if (br.type == REPEAT_SPARSE_OPTIMAL_P) {
|
if (br.type == REPEAT_SPARSE_OPTIMAL_P) {
|
||||||
assert(!rsi.table.empty());
|
assert(!rsi.table.empty());
|
||||||
memcpy(info_ptr + tableOffset, rsi.table.data(),
|
copy_bytes(info_ptr + tableOffset, rsi.table);
|
||||||
byte_length(rsi.table));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill the tug mask.
|
// Fill the tug mask.
|
||||||
@ -1702,6 +1700,7 @@ struct Factory {
|
|||||||
|
|
||||||
for (u32 i = 0; i < num_repeats; i++) {
|
for (u32 i = 0; i < num_repeats; i++) {
|
||||||
repeatOffsets[i] = offset;
|
repeatOffsets[i] = offset;
|
||||||
|
assert(repeats[i].first);
|
||||||
memcpy((char *)limex + offset, repeats[i].first.get(),
|
memcpy((char *)limex + offset, repeats[i].first.get(),
|
||||||
repeats[i].second);
|
repeats[i].second);
|
||||||
offset += repeats[i].second;
|
offset += repeats[i].second;
|
||||||
@ -1709,8 +1708,7 @@ struct Factory {
|
|||||||
|
|
||||||
// Write repeat offset lookup table.
|
// Write repeat offset lookup table.
|
||||||
assert(ISALIGNED_N((char *)limex + repeatOffsetsOffset, alignof(u32)));
|
assert(ISALIGNED_N((char *)limex + repeatOffsetsOffset, alignof(u32)));
|
||||||
memcpy((char *)limex + repeatOffsetsOffset, repeatOffsets.data(),
|
copy_bytes((char *)limex + repeatOffsetsOffset, repeatOffsets);
|
||||||
byte_length(repeatOffsets));
|
|
||||||
|
|
||||||
limex->repeatOffset = repeatOffsetsOffset;
|
limex->repeatOffset = repeatOffsetsOffset;
|
||||||
limex->repeatCount = num_repeats;
|
limex->repeatCount = num_repeats;
|
||||||
@ -1725,8 +1723,7 @@ struct Factory {
|
|||||||
limex->exReportOffset = exceptionReportsOffset;
|
limex->exReportOffset = exceptionReportsOffset;
|
||||||
assert(ISALIGNED_N((char *)limex + exceptionReportsOffset,
|
assert(ISALIGNED_N((char *)limex + exceptionReportsOffset,
|
||||||
alignof(ReportID)));
|
alignof(ReportID)));
|
||||||
memcpy((char *)limex + exceptionReportsOffset, reports.data(),
|
copy_bytes((char *)limex + exceptionReportsOffset, reports);
|
||||||
byte_length(reports));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -98,8 +98,7 @@ void fillNfa(NFA *nfa, lbr_common *c, ReportID report, const depth &repeatMin,
|
|||||||
info->packedCtrlSize = rsi.packedCtrlSize;
|
info->packedCtrlSize = rsi.packedCtrlSize;
|
||||||
info->horizon = rsi.horizon;
|
info->horizon = rsi.horizon;
|
||||||
info->minPeriod = minPeriod;
|
info->minPeriod = minPeriod;
|
||||||
memcpy(&info->packedFieldSizes, rsi.packedFieldSizes.data(),
|
copy_bytes(&info->packedFieldSizes, rsi.packedFieldSizes);
|
||||||
byte_length(rsi.packedFieldSizes));
|
|
||||||
info->patchCount = rsi.patchCount;
|
info->patchCount = rsi.patchCount;
|
||||||
info->patchSize = rsi.patchSize;
|
info->patchSize = rsi.patchSize;
|
||||||
info->encodingSize = rsi.encodingSize;
|
info->encodingSize = rsi.encodingSize;
|
||||||
@ -122,7 +121,7 @@ void fillNfa(NFA *nfa, lbr_common *c, ReportID report, const depth &repeatMin,
|
|||||||
nfa->length = verify_u32(len);
|
nfa->length = verify_u32(len);
|
||||||
info->length = verify_u32(sizeof(RepeatInfo)
|
info->length = verify_u32(sizeof(RepeatInfo)
|
||||||
+ sizeof(u64a) * (rsi.patchSize + 1));
|
+ sizeof(u64a) * (rsi.patchSize + 1));
|
||||||
memcpy(table, rsi.table.data(), byte_length(rsi.table));
|
copy_bytes(table, rsi.table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2687,12 +2687,6 @@ void fillInReportInfo(RoseEngine *engine, u32 reportOffset,
|
|||||||
sizeof(internal_report));
|
sizeof(internal_report));
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
|
||||||
void populateInvDkeyTable(char *ptr, const ReportManager &rm) {
|
|
||||||
vector<ReportID> table = rm.getDkeyToReportTable();
|
|
||||||
memcpy(ptr, table.data(), byte_length(table));
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool hasSimpleReports(const vector<Report> &reports) {
|
bool hasSimpleReports(const vector<Report> &reports) {
|
||||||
auto it = find_if(reports.begin(), reports.end(), isComplexReport);
|
auto it = find_if(reports.begin(), reports.end(), isComplexReport);
|
||||||
@ -4154,7 +4148,7 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
|||||||
engine->ekeyCount = rm.numEkeys();
|
engine->ekeyCount = rm.numEkeys();
|
||||||
engine->dkeyCount = rm.numDkeys();
|
engine->dkeyCount = rm.numDkeys();
|
||||||
engine->invDkeyOffset = dkeyOffset;
|
engine->invDkeyOffset = dkeyOffset;
|
||||||
populateInvDkeyTable(ptr + dkeyOffset, rm);
|
copy_bytes(ptr + dkeyOffset, rm.getDkeyToReportTable());
|
||||||
|
|
||||||
engine->somHorizon = ssm.somPrecision();
|
engine->somHorizon = ssm.somPrecision();
|
||||||
engine->somLocationCount = ssm.numSomSlots();
|
engine->somLocationCount = ssm.numSomSlots();
|
||||||
@ -4314,33 +4308,22 @@ aligned_unique_ptr<RoseEngine> RoseBuildImpl::buildFinalEngine(u32 minWidth) {
|
|||||||
buildLitBenefits(*this, engine.get(), base_lits_benefits_offset);
|
buildLitBenefits(*this, engine.get(), base_lits_benefits_offset);
|
||||||
|
|
||||||
// Copy in other tables
|
// Copy in other tables
|
||||||
memcpy(ptr + bc.engine_blob_base, bc.engine_blob.data(),
|
copy_bytes(ptr + bc.engine_blob_base, bc.engine_blob);
|
||||||
byte_length(bc.engine_blob));
|
copy_bytes(ptr + engine->literalOffset, literalTable);
|
||||||
|
copy_bytes(ptr + engine->roleOffset, bc.roleTable);
|
||||||
memcpy(ptr + engine->literalOffset, literalTable.data(),
|
copy_bytes(ptr + engine->leftOffset, leftInfoTable);
|
||||||
byte_length(literalTable));
|
|
||||||
memcpy(ptr + engine->roleOffset, bc.roleTable.data(),
|
|
||||||
byte_length(bc.roleTable));
|
|
||||||
copy(leftInfoTable.begin(), leftInfoTable.end(),
|
|
||||||
(LeftNfaInfo *)(ptr + engine->leftOffset));
|
|
||||||
|
|
||||||
fillLookaroundTables(ptr + lookaroundTableOffset,
|
fillLookaroundTables(ptr + lookaroundTableOffset,
|
||||||
ptr + lookaroundReachOffset, bc.lookaround);
|
ptr + lookaroundReachOffset, bc.lookaround);
|
||||||
|
|
||||||
fillInSomRevNfas(engine.get(), ssm, rev_nfa_table_offset, rev_nfa_offsets);
|
fillInSomRevNfas(engine.get(), ssm, rev_nfa_table_offset, rev_nfa_offsets);
|
||||||
memcpy(ptr + engine->predOffset, predTable.data(), byte_length(predTable));
|
copy_bytes(ptr + engine->predOffset, predTable);
|
||||||
memcpy(ptr + engine->rootRoleOffset, rootRoleTable.data(),
|
copy_bytes(ptr + engine->rootRoleOffset, rootRoleTable);
|
||||||
byte_length(rootRoleTable));
|
copy_bytes(ptr + engine->anchoredReportMapOffset, art);
|
||||||
memcpy(ptr + engine->anchoredReportMapOffset, art.data(), byte_length(art));
|
copy_bytes(ptr + engine->anchoredReportInverseMapOffset, arit);
|
||||||
memcpy(ptr + engine->anchoredReportInverseMapOffset, arit.data(),
|
copy_bytes(ptr + engine->multidirectOffset, mdr_reports);
|
||||||
byte_length(arit));
|
copy_bytes(ptr + engine->activeLeftIterOffset, activeLeftIter);
|
||||||
memcpy(ptr + engine->multidirectOffset, mdr_reports.data(),
|
copy_bytes(ptr + engine->sideOffset, sideTable);
|
||||||
byte_length(mdr_reports));
|
|
||||||
|
|
||||||
copy(activeLeftIter.begin(), activeLeftIter.end(),
|
|
||||||
(mmbit_sparse_iter *)(ptr + engine->activeLeftIterOffset));
|
|
||||||
|
|
||||||
memcpy(ptr + engine->sideOffset, sideTable.data(), byte_length(sideTable));
|
|
||||||
|
|
||||||
DEBUG_PRINTF("rose done %p\n", engine.get());
|
DEBUG_PRINTF("rose done %p\n", engine.get());
|
||||||
return engine;
|
return engine;
|
||||||
|
@ -33,8 +33,13 @@
|
|||||||
#ifndef UTIL_CONTAINER_H
|
#ifndef UTIL_CONTAINER_H
|
||||||
#define UTIL_CONTAINER_H
|
#define UTIL_CONTAINER_H
|
||||||
|
|
||||||
|
#include "ue2common.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace ue2 {
|
namespace ue2 {
|
||||||
@ -92,11 +97,35 @@ std::set<typename C::key_type> assoc_keys(const C &container) {
|
|||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return the length in bytes of the given vector of (POD) objects.
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
typename std::vector<T>::size_type byte_length(const std::vector<T> &vec) {
|
typename std::vector<T>::size_type byte_length(const std::vector<T> &vec) {
|
||||||
|
static_assert(std::is_pod<T>::value, "should be pod");
|
||||||
return vec.size() * sizeof(T);
|
return vec.size() * sizeof(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Copy the given vector of POD objects to the given location in memory.
|
||||||
|
* It is safe to give this function an empty vector.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void *copy_bytes(void *dest, const std::vector<T> &vec) {
|
||||||
|
static_assert(std::is_pod<T>::value, "should be pod");
|
||||||
|
assert(dest);
|
||||||
|
|
||||||
|
// Since we're generally using this function to write into the bytecode,
|
||||||
|
// dest should be appropriately aligned for T.
|
||||||
|
assert(ISALIGNED_N(dest, alignof(T)));
|
||||||
|
|
||||||
|
if (vec.empty()) {
|
||||||
|
return dest; // Protect memcpy against null pointers.
|
||||||
|
}
|
||||||
|
assert(vec.data() != nullptr);
|
||||||
|
return std::memcpy(dest, vec.data(), byte_length(vec));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename OrderedContainer1, typename OrderedContainer2>
|
template<typename OrderedContainer1, typename OrderedContainer2>
|
||||||
bool is_subset_of(const OrderedContainer1 &small, const OrderedContainer2 &big) {
|
bool is_subset_of(const OrderedContainer1 &small, const OrderedContainer2 &big) {
|
||||||
static_assert(std::is_same<typename OrderedContainer1::value_type,
|
static_assert(std::is_same<typename OrderedContainer1::value_type,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user