mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
554 lines
22 KiB
C++
554 lines
22 KiB
C++
/*
|
|
* Copyright (c) 2015-2017, Intel Corporation
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "ue2common.h"
|
|
#include "grey.h"
|
|
#include "fdr/fdr.h"
|
|
#include "fdr/fdr_compile.h"
|
|
#include "fdr/fdr_compile_internal.h"
|
|
#include "fdr/fdr_engine_description.h"
|
|
#include "fdr/teddy_compile.h"
|
|
#include "fdr/teddy_engine_description.h"
|
|
#include "hwlm/hwlm_internal.h"
|
|
#include "scratch.h"
|
|
#include "util/alloc.h"
|
|
#include "util/bitutils.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace std;
|
|
using namespace testing;
|
|
using namespace ue2;
|
|
|
|
#define NO_TEDDY_FAIL_ALLOWED 0
|
|
|
|
#if(NO_TEDDY_FAIL_ALLOWED)
|
|
#define CHECK_WITH_TEDDY_OK_TO_FAIL(fdr, hint) ASSERT_TRUE(fdr)
|
|
#else
|
|
#define CHECK_WITH_TEDDY_OK_TO_FAIL(fdr, hint) \
|
|
{ \
|
|
auto descr = getTeddyDescription(hint); \
|
|
if (descr && fdr.get() != nullptr) { \
|
|
return; \
|
|
} else { \
|
|
ASSERT_TRUE(fdr.get() != nullptr); \
|
|
} \
|
|
}
|
|
#endif
|
|
|
|
namespace {
|
|
|
|
struct match {
|
|
size_t end;
|
|
u32 id;
|
|
match(size_t end_in, u32 id_in) : end(end_in), id(id_in) {}
|
|
bool operator==(const match &b) const {
|
|
return end == b.end && id == b.id;
|
|
}
|
|
bool operator<(const match &b) const {
|
|
return tie(id, end) < tie(b.id, b.end);
|
|
}
|
|
match operator+(size_t adj) {
|
|
return match(end + adj, id);
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
T &operator<<(T &a, const match &b) {
|
|
a << "(" << b.end << ", " << b.id << ")";
|
|
return a;
|
|
}
|
|
|
|
template<typename T>
|
|
T &operator<<(T &a, const vector<match> &b) {
|
|
a << "(";
|
|
for (size_t i = 0; i < b.size(); i++) {
|
|
a << b[i];
|
|
}
|
|
a << ")";
|
|
return a;
|
|
}
|
|
|
|
map<u32, int> matchesCounts;
|
|
|
|
extern "C" {
|
|
|
|
static hwlmcb_rv_t countCallback(UNUSED size_t end, u32 id,
|
|
UNUSED struct hs_scratch *scratch) { // cppcheck-suppress constParameterCallback
|
|
matchesCounts[id]++;
|
|
return HWLM_CONTINUE_MATCHING;
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
} // namespace
|
|
|
|
static vector<u32> getValidFdrEngines() {
|
|
vector<u32> ret;
|
|
|
|
vector<FDREngineDescription> des;
|
|
getFdrDescriptions(&des);
|
|
for (vector<FDREngineDescription>::const_iterator it = des.begin();
|
|
it != des.end(); ++it) {
|
|
if (it->isValidOnTarget(get_current_target())) {
|
|
ret.push_back(it->getID());
|
|
}
|
|
}
|
|
vector<TeddyEngineDescription> tDes;
|
|
getTeddyDescriptions(&tDes);
|
|
for (vector<TeddyEngineDescription>::const_iterator it = tDes.begin();
|
|
it != tDes.end(); ++it) {
|
|
if (it->isValidOnTarget(get_current_target())) {
|
|
ret.push_back(it->getID());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static
|
|
bytecode_ptr<FDR> buildFDREngineHinted(const std::vector<hwlmLiteral> &lits,
|
|
bool make_small, u32 hint,
|
|
const target_t &target,
|
|
const Grey &grey) {
|
|
auto proto = fdrBuildProtoHinted(HWLM_ENGINE_FDR, lits, make_small, hint,
|
|
target, grey);
|
|
return fdrBuildTable(*proto, grey);
|
|
}
|
|
|
|
class FDRFloodp : public TestWithParam<u32> {
|
|
};
|
|
|
|
TEST_P(FDRFloodp, NoMask) {
|
|
const u32 hint = GetParam();
|
|
SCOPED_TRACE(hint);
|
|
const size_t dataSize = 1024;
|
|
vector<u8> data(dataSize);
|
|
u8 c = 0;
|
|
|
|
struct hs_scratch scratch;
|
|
scratch.fdr_conf = NULL;
|
|
while (c != 255) {
|
|
SCOPED_TRACE((unsigned int)c);
|
|
u8 bit = 1 << (c & 0x7);
|
|
u8 cAlt = c ^ bit;
|
|
memset(&data[0], c, dataSize);
|
|
|
|
vector<hwlmLiteral> lits;
|
|
|
|
// build literals of type "aaaa", "aaab", "baaa"
|
|
// of lengths 1, 2, 4, 8, both case-less and case-sensitive
|
|
for (int i = 0; i < 4; i++) {
|
|
string s(1 << i, c);
|
|
lits.push_back(hwlmLiteral(s, false, i * 8 + 0));
|
|
s[0] = cAlt;
|
|
lits.push_back(hwlmLiteral(s, false, i * 8 + 1));
|
|
lits.push_back(hwlmLiteral(s, true, i * 8 + 2));
|
|
s[0] = c;
|
|
s[s.size() - 1] = cAlt;
|
|
lits.push_back(hwlmLiteral(s, false, i * 8 + 3));
|
|
lits.push_back(hwlmLiteral(s, true, i * 8 + 4));
|
|
string sAlt(1 << i, cAlt);
|
|
lits.push_back(hwlmLiteral(sAlt, true, i * 8 + 5));
|
|
sAlt[0] = c;
|
|
lits.push_back(hwlmLiteral(sAlt, true, i * 8 + 6));
|
|
lits.push_back(hwlmLiteral(sAlt, false, i * 8 + 7));
|
|
}
|
|
|
|
auto fdr = buildFDREngineHinted(lits, false, hint, get_current_target(),
|
|
Grey());
|
|
CHECK_WITH_TEDDY_OK_TO_FAIL(fdr, hint);
|
|
|
|
hwlm_error_t fdrStatus = fdrExec(fdr.get(), &data[0], dataSize,
|
|
0, countCallback, &scratch, HWLM_ALL_GROUPS);
|
|
ASSERT_EQ(0, fdrStatus);
|
|
|
|
for (u8 i = 0; i < 4; i++) {
|
|
u32 cnt = dataSize - (1 << i) + 1;
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 0]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 1]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 3]);
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 7]);
|
|
if (isalpha(c) && (bit == CASE_BIT)) {
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 2]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 4]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 5]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 6]);
|
|
} else {
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 2]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 4]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 5]);
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 6]);
|
|
}
|
|
}
|
|
|
|
matchesCounts.clear();
|
|
memset(&data[0], cAlt, dataSize);
|
|
fdrStatus = fdrExec(fdr.get(), &data[0], dataSize,
|
|
0, countCallback, &scratch, HWLM_ALL_GROUPS);
|
|
ASSERT_EQ(0, fdrStatus);
|
|
|
|
for (u8 i = 0; i < 4; i++) {
|
|
u32 cnt = dataSize - (1 << i) + 1;
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 0]);
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 1]);
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 3]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 5]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 7]);
|
|
if (isalpha(c) && (bit == CASE_BIT)) {
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 2]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 4]);
|
|
ASSERT_EQ(cnt, matchesCounts[i * 8 + 6]);
|
|
} else {
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 2]);
|
|
ASSERT_EQ(i == 0 ? cnt : 0, matchesCounts[i * 8 + 4]);
|
|
ASSERT_EQ(0, matchesCounts[i * 8 + 6]);
|
|
}
|
|
}
|
|
matchesCounts.clear();
|
|
|
|
++c;
|
|
}
|
|
}
|
|
|
|
TEST_P(FDRFloodp, WithMask) {
|
|
const u32 hint = GetParam();
|
|
SCOPED_TRACE(hint);
|
|
const size_t dataSize = 1024;
|
|
vector<u8> data(dataSize);
|
|
u8 c = '\0';
|
|
|
|
struct hs_scratch scratch;
|
|
scratch.fdr_conf = NULL;
|
|
while (c != 255) {
|
|
u8 bit = 1 << (c & 0x7);
|
|
u8 cAlt = c ^ bit;
|
|
SCOPED_TRACE((unsigned int)c);
|
|
memset(&data[0], c, dataSize);
|
|
|
|
vector<hwlmLiteral> lits;
|
|
|
|
// literals of type "aaaa" of length 4, 12, and mask of length
|
|
// 1, 2, 4, 8, 0f type "b.......", "b......b" both case-less and case-sensitive
|
|
string s4(4, c);
|
|
string s4Alt(4, cAlt);
|
|
|
|
for (int i = 0; i < 4 ; i++) {
|
|
u32 mskLen = 1 << i;
|
|
vector<u8> msk(mskLen, '\0');
|
|
vector<u8> cmp(mskLen, '\0');
|
|
|
|
cmp[0] = cAlt;
|
|
msk[0] = '\xff';
|
|
// msk[f0000000] cmp[c0000000] lit[aaaa]
|
|
if (mskLen > s4.length()) {
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 0,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 1,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[f0000000] cmp[e0000000] lit[EEEE]
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 2,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[E0000000] cmp[E0000000] lit[eeee]
|
|
if ((cAlt & bit) == 0) {
|
|
msk[0] = ~bit;
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 3,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 4,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[f0000000] cmp[a0000000] lit[aaaa]
|
|
cmp[0] = c;
|
|
msk[0] = '\xff';
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 5,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 6,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
// msk[f0000000] cmp[a0000000] lit[cccc]
|
|
if (mskLen > s4Alt.length()) {
|
|
lits.push_back(hwlmLiteral(s4Alt, false, false, i * 12 + 7,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4Alt, true, false, i * 12 + 8,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
// msk[f0000000] cmp[e0000000] lit[EEEE]
|
|
lits.push_back(hwlmLiteral(s4Alt, true, false, i * 12 + 9,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
|
|
// msk[f0000000] cmp[e000000E] lit[eeee]
|
|
cmp[mskLen - 1] = cAlt;
|
|
msk[mskLen - 1] = '\xff';
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 10,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
// msk[f0000000] cmp[E000000E] lit[eeee]
|
|
cmp[0] = cAlt;
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 11,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
}
|
|
auto fdr = buildFDREngineHinted(lits, false, hint, get_current_target(),
|
|
Grey());
|
|
CHECK_WITH_TEDDY_OK_TO_FAIL(fdr, hint);
|
|
|
|
hwlm_error_t fdrStatus = fdrExec(fdr.get(), &data[0], dataSize,
|
|
0, countCallback, &scratch, HWLM_ALL_GROUPS);
|
|
ASSERT_EQ(0, fdrStatus);
|
|
|
|
const u32 cnt4 = dataSize - 4 + 1;
|
|
for (u8 i = 0; i < 4; i++) {
|
|
u32 mskLen = 1 << i;
|
|
u32 cntMask = MIN(cnt4, dataSize - mskLen + 1);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 0]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 1]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 2]);
|
|
if ((cAlt & bit) == 0) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 3]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 4]);
|
|
}
|
|
if (mskLen > 4) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 5]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 6]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 7]);
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 8]);
|
|
} else {
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 8]);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT_EQ(cnt4, matchesCounts[i * 12 + 5]);
|
|
ASSERT_EQ(cnt4, matchesCounts[i * 12 + 6]);
|
|
}
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 9]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 10]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 11]);
|
|
}
|
|
}
|
|
|
|
memset(&data[0], cAlt, dataSize);
|
|
matchesCounts.clear();
|
|
fdrStatus = fdrExec(fdr.get(), &data[0], dataSize,
|
|
0, countCallback, &scratch, HWLM_ALL_GROUPS);
|
|
ASSERT_EQ(0, fdrStatus);
|
|
|
|
for (u8 i = 0; i < 4; i++) {
|
|
u32 mskLen = 1 << i;
|
|
u32 cntMask = MIN(cnt4, dataSize - mskLen + 1);
|
|
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 0]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 3]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 5]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 6]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 7]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 8]);
|
|
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 9]);
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
ASSERT_EQ(mskLen > 4 ? cntMask : 0, matchesCounts[i * 12 + 1]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 2]);
|
|
if(islower(c)) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 4]);
|
|
} else {
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 4]);
|
|
}
|
|
ASSERT_EQ(mskLen == 1 ? cnt4 : 0, matchesCounts[i * 12 + 10]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 11]);
|
|
} else {
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 1]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 2]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 4]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 10]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 11]);
|
|
}
|
|
}
|
|
matchesCounts.clear();
|
|
|
|
++c;
|
|
}
|
|
}
|
|
|
|
TEST_P(FDRFloodp, StreamingMask) {
|
|
const u32 hint = GetParam();
|
|
SCOPED_TRACE(hint);
|
|
const size_t fake_history_size = 16;
|
|
const vector<u8> fake_history(fake_history_size, 0);
|
|
const size_t dataSize = 1024;
|
|
vector<u8> data(dataSize);
|
|
vector<u8> tempdata(dataSize + fake_history_size); // headroom
|
|
u8 c = '\0';
|
|
|
|
struct hs_scratch scratch;
|
|
scratch.fdr_conf = NULL;
|
|
while (c != 255) {
|
|
u8 bit = 1 << (c & 0x7);
|
|
u8 cAlt = c ^ bit;
|
|
SCOPED_TRACE((unsigned int)c);
|
|
memset(&data[0], c, dataSize);
|
|
|
|
vector<hwlmLiteral> lits;
|
|
|
|
// literals of type "aaaa" of length 4, 12, and mask of length
|
|
// 1, 2, 4, 8, 0f type "b.......", "b......b" both case-less and case-sensitive
|
|
string s4(4, c);
|
|
string s4Alt(4, cAlt);
|
|
|
|
for (int i = 0; i < 4 ; i++) {
|
|
u32 mskLen = 1 << i;
|
|
vector<u8> msk(mskLen, '\0');
|
|
vector<u8> cmp(mskLen, '\0');
|
|
|
|
cmp[0] = cAlt;
|
|
msk[0] = '\xff';
|
|
// msk[f0000000] cmp[c0000000] lit[aaaa]
|
|
if (mskLen > s4.length()) {
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 0,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 1,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[f0000000] cmp[e0000000] lit[EEEE]
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 2,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[E0000000] cmp[E0000000] lit[eeee]
|
|
if ((cAlt & bit) == 0) {
|
|
msk[0] = ~bit;
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 3,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 4,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
// msk[f0000000] cmp[a0000000] lit[aaaa]
|
|
cmp[0] = c;
|
|
msk[0] = '\xff';
|
|
lits.push_back(hwlmLiteral(s4, false, false, i * 12 + 5,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 6,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
// msk[f0000000] cmp[a0000000] lit[cccc]
|
|
if (mskLen > s4Alt.length()) {
|
|
lits.push_back(hwlmLiteral(s4Alt, false, false, i * 12 + 7,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
lits.push_back(hwlmLiteral(s4Alt, true, false, i * 12 + 8,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
// msk[f0000000] cmp[e0000000] lit[EEEE]
|
|
lits.push_back(hwlmLiteral(s4Alt, true, false, i * 12 + 9,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
|
|
// msk[f0000000] cmp[e000000E] lit[eeee]
|
|
cmp[mskLen - 1] = cAlt;
|
|
msk[mskLen - 1] = '\xff';
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 10,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
// msk[f0000000] cmp[E000000E] lit[eeee]
|
|
cmp[0] = cAlt;
|
|
lits.push_back(hwlmLiteral(s4, true, false, i * 12 + 11,
|
|
HWLM_ALL_GROUPS, msk, cmp));
|
|
}
|
|
}
|
|
auto fdr = buildFDREngineHinted(lits, false, hint, get_current_target(),
|
|
Grey());
|
|
CHECK_WITH_TEDDY_OK_TO_FAIL(fdr, hint);
|
|
|
|
const u32 cnt4 = dataSize - 4 + 1;
|
|
|
|
for (u32 streamChunk = 1; streamChunk <= 16; streamChunk *= 2) {
|
|
matchesCounts.clear();
|
|
const u8 *d = data.data();
|
|
// reference past the end of fake history to allow headroom
|
|
const u8 *fhist = fake_history.data() + fake_history_size;
|
|
hwlm_error_t fdrStatus = fdrExecStreaming(fdr.get(), fhist, 0, d, streamChunk, 0,
|
|
countCallback, &scratch,
|
|
HWLM_ALL_GROUPS);
|
|
ASSERT_EQ(0, fdrStatus);
|
|
for (u32 j = streamChunk; j < dataSize; j += streamChunk) {
|
|
if (j < 16) {
|
|
/* allow 16 bytes headroom on read to avoid invalid
|
|
* memory read during the FDR zone creation.*/
|
|
memset(tempdata.data(), c, dataSize + fake_history_size);
|
|
const u8 *tmp_d = tempdata.data() + fake_history_size;
|
|
fdrStatus = fdrExecStreaming(fdr.get(), tmp_d, j, tmp_d + j,
|
|
streamChunk, 0, countCallback,
|
|
&scratch, HWLM_ALL_GROUPS);
|
|
} else {
|
|
fdrStatus = fdrExecStreaming(fdr.get(), d + j - 8, 8, d + j,
|
|
streamChunk, 0, countCallback,
|
|
&scratch, HWLM_ALL_GROUPS);
|
|
}
|
|
ASSERT_EQ(0, fdrStatus);
|
|
}
|
|
|
|
for (u8 i = 0; i < 4; i++) {
|
|
u32 mskLen = 1 << i;
|
|
u32 cntMask = MIN(cnt4, dataSize - mskLen + 1);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 0]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 1]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 2]);
|
|
if ((cAlt & bit) == 0) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 3]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 4]);
|
|
}
|
|
if (mskLen > 4) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 5]);
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 6]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 7]);
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 8]);
|
|
} else {
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 8]);
|
|
}
|
|
}
|
|
else {
|
|
ASSERT_EQ(cnt4, matchesCounts[i * 12 + 5]);
|
|
ASSERT_EQ(cnt4, matchesCounts[i * 12 + 6]);
|
|
}
|
|
if (bit == CASE_BIT && isalpha(c)) {
|
|
ASSERT_EQ(cntMask, matchesCounts[i * 12 + 9]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 10]);
|
|
ASSERT_EQ(0, matchesCounts[i * 12 + 11]);
|
|
}
|
|
}
|
|
}
|
|
|
|
++c;
|
|
}
|
|
matchesCounts.clear();
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(FDRFlood, FDRFloodp, ValuesIn(getValidFdrEngines()));
|
|
|