unique_ptr<HWLMProto> hwlmBuildProto(vector<hwlmLiteral> &lits, bool make_small, const CompileContext &cc) { assert(!lits.empty()); dumpLits(lits); // Check that we haven't exceeded the maximum number of literals. if (lits.size() > cc.grey.limitLiteralCount) { throw ResourceLimitError(); } // Safety and resource limit checks. u64a total_chars = 0; for (const auto &lit : lits) { assert(!lit.s.empty()); if (lit.s.length() > cc.grey.limitLiteralLength) { throw ResourceLimitError(); } total_chars += lit.s.length(); if (total_chars > cc.grey.limitLiteralMatcherChars) { throw ResourceLimitError(); } // We do not allow the all-ones ID, as we reserve that for internal use // within literal matchers. if (lit.id == 0xffffffffu) { assert(!"reserved id 0xffffffff used"); throw CompileError("Internal error."); } } unique_ptr<HWLMProto> proto; DEBUG_PRINTF("building table with %zu strings\n", lits.size()); assert(everyoneHasGroups(lits)); if (isNoodleable(lits, cc)) { DEBUG_PRINTF("build noodle table\n"); proto = ue2::make_unique<HWLMProto>(HWLM_ENGINE_NOOD, lits); } else { DEBUG_PRINTF("building a new deal\n"); proto = fdrBuildProto(HWLM_ENGINE_FDR, lits, make_small, cc.target_info, cc.grey); if (!proto) { return nullptr; } } return proto; }
u32 ReportManager::getInternalId(const Report &ir) { auto it = reportIdToInternalMap.find(ir); if (it != reportIdToInternalMap.end()) { DEBUG_PRINTF("existing report %zu\n", it->second); return it->second; } // Construct a new internal report and assign it a ReportID. if (numReports() >= grey.limitReportCount) { throw ResourceLimitError(); } u32 size = reportIds.size(); reportIds.push_back(ir); reportIdToInternalMap[ir] = size; DEBUG_PRINTF("new report %u\n", size); return size; }
bytecode_ptr<HWLM> hwlmBuild(const HWLMProto &proto, const CompileContext &cc, UNUSED hwlm_group_t expected_groups) { size_t engSize = 0; shared_ptr<void> eng; const auto &lits = proto.lits; DEBUG_PRINTF("building table with %zu strings\n", lits.size()); if (proto.engType == HWLM_ENGINE_NOOD) { DEBUG_PRINTF("build noodle table\n"); const hwlmLiteral &lit = lits.front(); auto noodle = noodBuildTable(lit); if (noodle) { engSize = noodle.size(); } eng = move(noodle); } else { DEBUG_PRINTF("building a new deal\n"); auto fdr = fdrBuildTable(proto, cc.grey); if (fdr) { engSize = fdr.size(); } eng = move(fdr); } if (!eng) { return nullptr; } assert(engSize); if (engSize > cc.grey.limitLiteralMatcherSize) { throw ResourceLimitError(); } const size_t hwlm_len = ROUNDUP_CL(sizeof(HWLM)) + engSize; auto h = make_zeroed_bytecode_ptr<HWLM>(hwlm_len, 64); h->type = proto.engType; memcpy(HWLM_DATA(h.get()), eng.get(), engSize); return h; }
aligned_unique_ptr<HWLM> hwlmBuild(const vector<hwlmLiteral> &lits, hwlmStreamingControl *stream_control, bool make_small, const CompileContext &cc, hwlm_group_t expected_groups) { assert(!lits.empty()); dumpLits(lits); if (stream_control) { assert(stream_control->history_min <= stream_control->history_max); } // Check that we haven't exceeded the maximum number of literals. if (lits.size() > cc.grey.limitLiteralCount) { throw ResourceLimitError(); } // Safety and resource limit checks. u64a total_chars = 0; for (const auto &lit : lits) { assert(!lit.s.empty()); if (lit.s.length() > cc.grey.limitLiteralLength) { throw ResourceLimitError(); } total_chars += lit.s.length(); if (total_chars > cc.grey.limitLiteralMatcherChars) { throw ResourceLimitError(); } // We do not allow the all-ones ID, as we reserve that for internal use // within literal matchers. if (lit.id == 0xffffffffu) { assert(!"reserved id 0xffffffff used"); throw CompileError("Internal error."); } } u8 engType = 0; size_t engSize = 0; shared_ptr<void> eng; DEBUG_PRINTF("building table with %zu strings\n", lits.size()); assert(everyoneHasGroups(lits)); if (isNoodleable(lits, stream_control, cc)) { DEBUG_PRINTF("build noodle table\n"); engType = HWLM_ENGINE_NOOD; const hwlmLiteral &lit = lits.front(); auto noodle = noodBuildTable((const u8 *)lit.s.c_str(), lit.s.length(), lit.nocase, lit.id); if (noodle) { engSize = noodSize(noodle.get()); } if (stream_control) { // For now, a single literal still goes to noodle and asks // for a great big history stream_control->literal_history_required = lit.s.length() - 1; assert(stream_control->literal_history_required <= stream_control->history_max); stream_control->literal_stream_state_required = 0; } eng = move(noodle); } else { DEBUG_PRINTF("building a new deal\n"); engType = HWLM_ENGINE_FDR; auto fdr = fdrBuildTable(lits, make_small, cc.target_info, cc.grey, stream_control); if (fdr) { engSize = fdrSize(fdr.get()); } eng = move(fdr); } if (!eng) { return nullptr; } assert(engSize); if (engSize > cc.grey.limitLiteralMatcherSize) { throw ResourceLimitError(); } auto h = aligned_zmalloc_unique<HWLM>(ROUNDUP_CL(sizeof(HWLM)) + engSize); h->type = engType; memcpy(HWLM_DATA(h.get()), eng.get(), engSize); if (engType == HWLM_ENGINE_FDR && cc.grey.hamsterAccelForward) { buildForwardAccel(h.get(), lits, expected_groups); } if (stream_control) { DEBUG_PRINTF("requires %zu (of max %zu) bytes of history\n", stream_control->literal_history_required, stream_control->history_max); assert(stream_control->literal_history_required <= stream_control->history_max); } return h; }