Fix unsafe and inefficient uses of copy_string

Add a new overload to `copy_string` that takes the input characters plus
size. The new overload avoids inefficient scanning of the input for the
null terminator in cases where we know the size beforehand. Furthermore,
this overload *must* be used when dealing with input character sequences
that may have no null terminator, e.g., when the input is from a
`std::string_view` object.
This commit is contained in:
Dominik Charousset 2023-11-02 17:37:11 +01:00
parent 4eb1b71d1b
commit cebb85b1e8
25 changed files with 85 additions and 56 deletions

View file

@ -157,7 +157,8 @@ int TraceState::LogTrace(const char* fmt, ...) {
} }
if ( ! loc.filename ) { if ( ! loc.filename ) {
loc.filename = util::copy_string("<no filename>"); static constexpr const char str[] = "<no filename>";
loc.filename = util::copy_string(str, std::size(str) - 1);
loc.last_line = 0; loc.last_line = 0;
} }
@ -675,7 +676,8 @@ string get_context_description(const Stmt* stmt, const Frame* frame) {
if ( stmt ) if ( stmt )
loc = *stmt->GetLocationInfo(); loc = *stmt->GetLocationInfo();
else { else {
loc.filename = util::copy_string("<no filename>"); static constexpr const char str[] = "<no filename>";
loc.filename = util::copy_string(str, std::size(str) - 1);
loc.last_line = 0; loc.last_line = 0;
} }

View file

@ -3362,7 +3362,7 @@ bool FieldAssignExpr::PromoteTo(TypePtr t) {
bool FieldAssignExpr::IsRecordElement(TypeDecl* td) const { bool FieldAssignExpr::IsRecordElement(TypeDecl* td) const {
if ( td ) { if ( td ) {
td->type = op->GetType(); td->type = op->GetType();
td->id = util::copy_string(field_name.c_str()); td->id = util::copy_string(field_name.c_str(), field_name.size());
} }
return true; return true;

View file

@ -1752,7 +1752,7 @@ WhenInfo::WhenInfo(ExprPtr arg_cond, FuncType::CaptureList* arg_cl, bool arg_is_
auto param_list = new type_decl_list(); auto param_list = new type_decl_list();
auto count_t = base_type(TYPE_COUNT); auto count_t = base_type(TYPE_COUNT);
param_list->push_back(new TypeDecl(util::copy_string(lambda_param_id.c_str()), count_t)); param_list->push_back(new TypeDecl(util::copy_string(lambda_param_id.c_str(), lambda_param_id.size()), count_t));
auto params = make_intrusive<RecordType>(param_list); auto params = make_intrusive<RecordType>(param_list);
lambda_ft = make_intrusive<FuncType>(params, base_type(TYPE_ANY), FUNC_FLAVOR_FUNCTION); lambda_ft = make_intrusive<FuncType>(params, base_type(TYPE_ANY), FUNC_FLAVOR_FUNCTION);

View file

@ -752,6 +752,8 @@ const u_char* StringVal::Bytes() const { return AsString()->Bytes(); }
const char* StringVal::CheckString() const { return AsString()->CheckString(); } const char* StringVal::CheckString() const { return AsString()->CheckString(); }
std::pair<const char*, size_t> StringVal::CheckStringWithSize() const { return AsString()->CheckStringWithSize(); }
string StringVal::ToStdString() const { string StringVal::ToStdString() const {
auto* bs = AsString(); auto* bs = AsString();
return {(char*)bs->Bytes(), static_cast<size_t>(bs->Len())}; return {(char*)bs->Bytes(), static_cast<size_t>(bs->Len())};

View file

@ -546,6 +546,7 @@ public:
int Len() const; int Len() const;
const u_char* Bytes() const; const u_char* Bytes() const;
const char* CheckString() const; const char* CheckString() const;
std::pair<const char*, size_t> CheckStringWithSize() const;
// Note that one needs to de-allocate the return value of // Note that one needs to de-allocate the return value of
// ExpandedString() to avoid a memory leak. // ExpandedString() to avoid a memory leak.

View file

@ -135,10 +135,10 @@ void String::Set(std::string_view str) {
void String::Set(const String& str) { *this = str; } void String::Set(const String& str) { *this = str; }
const char* String::CheckString() const { std::pair<const char*, size_t> String::CheckStringWithSize() const {
void* nulTerm; void* nulTerm;
if ( n == 0 ) if ( n == 0 )
return ""; return {"", 0};
nulTerm = memchr(b, '\0', n + final_NUL); nulTerm = memchr(b, '\0', n + final_NUL);
if ( nulTerm != &b[n] ) { if ( nulTerm != &b[n] ) {
@ -151,12 +151,15 @@ const char* String::CheckString() const {
reporter->Error("string without NUL terminator: \"%s\"", exp_s); reporter->Error("string without NUL terminator: \"%s\"", exp_s);
delete[] exp_s; delete[] exp_s;
return "<string-with-NUL>"; static constexpr const char result[] = "<string-with-NUL>";
return {result, std::size(result) - 1};
} }
return (const char*)b; return {(const char*)b, n};
} }
const char* String::CheckString() const { return CheckStringWithSize().first; }
char* String::Render(int format, int* len) const { char* String::Render(int format, int* len) const {
// Maximum character expansion is as \xHH, so a factor of 4. // Maximum character expansion is as \xHH, so a factor of 4.
char* s = new char[n * 4 + 1]; // +1 is for final '\0' char* s = new char[n * 4 + 1]; // +1 is for final '\0'

View file

@ -84,6 +84,11 @@ public:
*/ */
const char* CheckString() const; const char* CheckString() const;
/**
* Like @c CheckString(), but also returns the length of the string.
*/
std::pair<const char*, size_t> CheckStringWithSize() const;
enum render_style { enum render_style {
ESC_NONE = 0, ESC_NONE = 0,
ESC_ESC = (1 << 1), // '\' -> "\\" ESC_ESC = (1 << 1), // '\' -> "\\"

View file

@ -215,8 +215,8 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) {
string source((const char*)bsource->Bytes(), bsource->Len()); string source((const char*)bsource->Bytes(), bsource->Len());
ReaderBackend::ReaderInfo rinfo; ReaderBackend::ReaderInfo rinfo;
rinfo.source = util::copy_string(source.c_str()); rinfo.source = util::copy_string(source.c_str(), source.size());
rinfo.name = util::copy_string(name.c_str()); rinfo.name = util::copy_string(name.c_str(), name.size());
auto mode_val = description->GetFieldOrDefault("mode"); auto mode_val = description->GetFieldOrDefault("mode");
auto mode = mode_val->AsEnumVal(); auto mode = mode_val->AsEnumVal();
@ -244,7 +244,8 @@ bool Manager::CreateStream(Stream* info, RecordVal* description) {
auto index = info->config->RecreateIndex(*k); auto index = info->config->RecreateIndex(*k);
string key = index->Idx(0)->AsString()->CheckString(); string key = index->Idx(0)->AsString()->CheckString();
string value = v->GetVal()->AsString()->CheckString(); string value = v->GetVal()->AsString()->CheckString();
rinfo.config.insert(std::make_pair(util::copy_string(key.c_str()), util::copy_string(value.c_str()))); rinfo.config.insert(std::make_pair(util::copy_string(key.c_str(), key.size()),
util::copy_string(value.c_str(), value.size())));
} }
} }

View file

@ -152,7 +152,7 @@ bool Ascii::OpenFile() {
if ( ! read_location ) { if ( ! read_location ) {
read_location = LocationPtr(new zeek::detail::Location()); read_location = LocationPtr(new zeek::detail::Location());
read_location->filename = util::copy_string(fname.c_str()); read_location->filename = util::copy_string(fname.c_str(), fname.size());
} }
StopWarningSuppression(); StopWarningSuppression();

View file

@ -120,7 +120,7 @@ threading::Value* Benchmark::EntryToVal(TypeTag type, TypeTag subtype) {
case TYPE_STRING: { case TYPE_STRING: {
std::string rnd = RandomString(10); std::string rnd = RandomString(10);
val->val.string_val.data = util::copy_string(rnd.c_str()); val->val.string_val.data = util::copy_string(rnd.c_str(), rnd.size());
val->val.string_val.length = rnd.size(); val->val.string_val.length = rnd.size();
break; break;
} }

View file

@ -222,11 +222,11 @@ bool Config::DoUpdate() {
Value** fields = new Value*[2]; Value** fields = new Value*[2];
Value* keyval = new threading::Value(TYPE_STRING, true); Value* keyval = new threading::Value(TYPE_STRING, true);
keyval->val.string_val.length = key.size(); keyval->val.string_val.length = key.size();
keyval->val.string_val.data = util::copy_string(key.c_str()); keyval->val.string_val.data = util::copy_string(key.c_str(), key.size());
fields[0] = keyval; fields[0] = keyval;
Value* val = new threading::Value(TYPE_STRING, true); Value* val = new threading::Value(TYPE_STRING, true);
val->val.string_val.length = value.size(); val->val.string_val.length = value.size();
val->val.string_val.data = util::copy_string(value.c_str()); val->val.string_val.data = util::copy_string(value.c_str(), value.size());
fields[1] = val; fields[1] = val;
if ( Info().mode == MODE_STREAM ) if ( Info().mode == MODE_STREAM )
@ -238,13 +238,15 @@ bool Config::DoUpdate() {
{ {
Value** vals = new Value*[4]; Value** vals = new Value*[4];
vals[0] = new Value(TYPE_STRING, true); vals[0] = new Value(TYPE_STRING, true);
vals[0]->val.string_val.data = util::copy_string(Info().name); auto val0_len = strlen(Info().name);
vals[0]->val.string_val.length = strlen(Info().name); vals[0]->val.string_val.data = util::copy_string(Info().name, val0_len);
vals[0]->val.string_val.length = val0_len;
vals[1] = new Value(TYPE_STRING, true); vals[1] = new Value(TYPE_STRING, true);
vals[1]->val.string_val.data = util::copy_string(Info().source); auto val1_len = strlen(Info().source);
vals[1]->val.string_val.length = strlen(Info().source); vals[1]->val.string_val.data = util::copy_string(Info().source, val1_len);
vals[1]->val.string_val.length = val1_len;
vals[2] = new Value(TYPE_STRING, true); vals[2] = new Value(TYPE_STRING, true);
vals[2]->val.string_val.data = util::copy_string(key.c_str()); vals[2]->val.string_val.data = util::copy_string(key.c_str(), key.size());
vals[2]->val.string_val.length = key.size(); vals[2]->val.string_val.length = key.size();
vals[3] = eventval; vals[3] = eventval;

View file

@ -679,11 +679,13 @@ bool Raw::DoUpdate() {
Value** vals = new Value*[4]; Value** vals = new Value*[4];
vals[0] = new Value(TYPE_STRING, true); vals[0] = new Value(TYPE_STRING, true);
vals[0]->val.string_val.data = util::copy_string(Info().name); auto val0_len = strlen(Info().name);
vals[0]->val.string_val.length = strlen(Info().name); vals[0]->val.string_val.data = util::copy_string(Info().name, val0_len);
vals[0]->val.string_val.length = val0_len;
vals[1] = new Value(TYPE_STRING, true); vals[1] = new Value(TYPE_STRING, true);
vals[1]->val.string_val.data = util::copy_string(Info().source); auto val1_len = strlen(Info().source);
vals[1]->val.string_val.length = strlen(Info().source); vals[1]->val.string_val.data = util::copy_string(Info().source, val1_len);
vals[1]->val.string_val.length = val1_len;
vals[2] = new Value(TYPE_COUNT, true); vals[2] = new Value(TYPE_COUNT, true);
vals[2]->val.int_val = code; vals[2]->val.int_val = code;
vals[3] = new Value(TYPE_BOOL, true); vals[3] = new Value(TYPE_BOOL, true);

View file

@ -803,14 +803,15 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg) {
if ( const auto& val = filter->field_name_map->Find(fn) ) { if ( const auto& val = filter->field_name_map->Find(fn) ) {
delete[] filter->fields[j]->name; delete[] filter->fields[j]->name;
filter->fields[j]->name = util::copy_string(val->AsStringVal()->CheckString()); auto [data, len] = val->AsStringVal()->CheckStringWithSize();
filter->fields[j]->name = util::copy_string(data, len);
} }
} }
arg_fields[j] = new threading::Field(*filter->fields[j]); arg_fields[j] = new threading::Field(*filter->fields[j]);
} }
info = new WriterBackend::WriterInfo; info = new WriterBackend::WriterInfo;
info->path = util::copy_string(path.c_str()); info->path = util::copy_string(path.c_str(), path.size());
info->network_time = run_state::network_time; info->network_time = run_state::network_time;
auto* filter_config_table = filter->config->AsTable(); auto* filter_config_table = filter->config->AsTable();
@ -821,7 +822,8 @@ bool Manager::Write(EnumVal* id, RecordVal* columns_arg) {
auto index = filter->config->RecreateIndex(*k); auto index = filter->config->RecreateIndex(*k);
string key = index->Idx(0)->AsString()->CheckString(); string key = index->Idx(0)->AsString()->CheckString();
string value = v->GetVal()->AsString()->CheckString(); string value = v->GetVal()->AsString()->CheckString();
info->config.insert(std::make_pair(util::copy_string(key.c_str()), util::copy_string(value.c_str()))); info->config.emplace(util::copy_string(key.c_str(), key.size()),
util::copy_string(value.c_str(), value.size()));
} }
// CreateWriter() will set the other fields in info. // CreateWriter() will set the other fields in info.
@ -883,14 +885,15 @@ threading::Value* Manager::ValToLogVal(std::optional<ZVal>& val, Type* ty) {
const char* s = ty->AsEnumType()->Lookup(val->AsInt()); const char* s = ty->AsEnumType()->Lookup(val->AsInt());
if ( s ) { if ( s ) {
lval->val.string_val.data = util::copy_string(s); auto len = strlen(s);
lval->val.string_val.length = strlen(s); lval->val.string_val.data = util::copy_string(s, len);
lval->val.string_val.length = len;
} }
else { else {
auto err_msg = "enum type does not contain value:" + std::to_string(val->AsInt()); auto err_msg = "enum type does not contain value:" + std::to_string(val->AsInt());
ty->Error(err_msg.c_str()); ty->Error(err_msg.c_str());
lval->val.string_val.data = util::copy_string(""); lval->val.string_val.data = util::copy_string("", 0);
lval->val.string_val.length = 0; lval->val.string_val.length = 0;
} }
break; break;
@ -935,9 +938,10 @@ threading::Value* Manager::ValToLogVal(std::optional<ZVal>& val, Type* ty) {
case TYPE_FILE: { case TYPE_FILE: {
const File* f = val->AsFile(); const File* f = val->AsFile();
string s = f->Name(); const char* s = f->Name();
lval->val.string_val.data = util::copy_string(s.c_str()); auto len = strlen(s);
lval->val.string_val.length = s.size(); lval->val.string_val.data = util::copy_string(s, len);
lval->val.string_val.length = len;
break; break;
} }
@ -946,8 +950,9 @@ threading::Value* Manager::ValToLogVal(std::optional<ZVal>& val, Type* ty) {
const Func* f = val->AsFunc(); const Func* f = val->AsFunc();
f->Describe(&d); f->Describe(&d);
const char* s = d.Description(); const char* s = d.Description();
lval->val.string_val.data = util::copy_string(s); auto len = strlen(s);
lval->val.string_val.length = strlen(s); lval->val.string_val.data = util::copy_string(s, len);
lval->val.string_val.length = len;
break; break;
} }

View file

@ -73,9 +73,7 @@ broker::data WriterBackend::WriterInfo::ToBroker() const {
auto t = broker::table(); auto t = broker::table();
for ( config_map::const_iterator i = config.begin(); i != config.end(); ++i ) { for ( config_map::const_iterator i = config.begin(); i != config.end(); ++i ) {
auto key = std::string(i->first); t.emplace(std::string{i->first}, std::string{i->second});
auto value = std::string(i->second);
t.insert(std::make_pair(key, value));
} }
auto bppf = post_proc_func ? post_proc_func : ""; auto bppf = post_proc_func ? post_proc_func : "";
@ -98,7 +96,7 @@ bool WriterBackend::WriterInfo::FromBroker(broker::data d) {
if ( ! (bpath && brotation_base && brotation_interval && bnetwork_time && bconfig && bppf) ) if ( ! (bpath && brotation_base && brotation_interval && bnetwork_time && bconfig && bppf) )
return false; return false;
path = util::copy_string(bpath->c_str()); path = util::copy_string(bpath->c_str(), bpath->size());
post_proc_func = util::copy_string(bppf->c_str()); post_proc_func = util::copy_string(bppf->c_str());
rotation_base = *brotation_base; rotation_base = *brotation_base;
rotation_interval = *brotation_interval; rotation_interval = *brotation_interval;
@ -111,7 +109,7 @@ bool WriterBackend::WriterInfo::FromBroker(broker::data d) {
if ( ! (k && v) ) if ( ! (k && v) )
return false; return false;
auto p = std::make_pair(util::copy_string(k->c_str()), util::copy_string(v->c_str())); auto p = std::make_pair(util::copy_string(k->c_str(), k->size()), util::copy_string(v->c_str(), v->size()));
config.insert(p); config.insert(p);
} }

View file

@ -405,7 +405,7 @@ int CPP_FieldMapping::ComputeOffset(InitsManager* im) const {
if ( fm_offset < 0 ) { // field does not exist, create it if ( fm_offset < 0 ) { // field does not exist, create it
fm_offset = r->NumFields(); fm_offset = r->NumFields();
auto id = util::copy_string(field_name.c_str()); auto id = util::copy_string(field_name.c_str(), field_name.size());
auto type = im->Types(field_type); auto type = im->Types(field_type);
AttributesPtr attrs; AttributesPtr attrs;

View file

@ -146,7 +146,7 @@ TypePtr rt::create_record_type(const std::string& ns, const std::string& id,
attrs->AddAttr(std::move(log_)); attrs->AddAttr(std::move(log_));
} }
decls->append(new TypeDecl(util::copy_string(f.id.c_str()), f.type, std::move(attrs))); decls->append(new TypeDecl(util::copy_string(f.id.c_str(), f.id.size()), f.type, std::move(attrs)));
} }
return make_intrusive<RecordType>(decls.release()); return make_intrusive<RecordType>(decls.release());

View file

@ -72,7 +72,7 @@ public:
ReporterMessage(Type arg_type, MsgThread* thread, std::string_view arg_msg) ReporterMessage(Type arg_type, MsgThread* thread, std::string_view arg_msg)
: OutputMessage<MsgThread>("ReporterMessage", thread) { : OutputMessage<MsgThread>("ReporterMessage", thread) {
type = arg_type; type = arg_type;
msg = util::copy_string(arg_msg.data()); msg = util::copy_string(arg_msg.data(), arg_msg.size());
} }
~ReporterMessage() override { delete[] msg; } ~ReporterMessage() override { delete[] msg; }
@ -104,7 +104,7 @@ public:
DebugMessage(DebugStream arg_stream, MsgThread* thread, std::string_view arg_msg) DebugMessage(DebugStream arg_stream, MsgThread* thread, std::string_view arg_msg)
: OutputMessage<MsgThread>("DebugMessage", thread) { : OutputMessage<MsgThread>("DebugMessage", thread) {
stream = arg_stream; stream = arg_stream;
msg = util::copy_string(arg_msg.data()); msg = util::copy_string(arg_msg.data(), arg_msg.size());
} }
~DebugMessage() override { delete[] msg; } ~DebugMessage() override { delete[] msg; }

View file

@ -30,7 +30,7 @@ bool Field::Read(detail::SerializationFormat* fmt) {
if ( ! fmt->Read(&tmp_secondary_name, "secondary_name") ) if ( ! fmt->Read(&tmp_secondary_name, "secondary_name") )
return false; return false;
secondary_name = util::copy_string(tmp_secondary_name.c_str()); secondary_name = util::copy_string(tmp_secondary_name.c_str(), tmp_secondary_name.size());
} }
else else
secondary_name = nullptr; secondary_name = nullptr;
@ -41,7 +41,7 @@ bool Field::Read(detail::SerializationFormat* fmt) {
if ( ! success ) if ( ! success )
return false; return false;
name = util::copy_string(tmp_name.c_str()); name = util::copy_string(tmp_name.c_str(), tmp_name.size());
type = static_cast<TypeTag>(t); type = static_cast<TypeTag>(t);
subtype = static_cast<TypeTag>(st); subtype = static_cast<TypeTag>(st);

View file

@ -287,7 +287,7 @@ Value* Ascii::ParseValue(const string& s, const string& name, TypeTag type, Type
// Remove the '/'s // Remove the '/'s
candidate.erase(0, 1); candidate.erase(0, 1);
candidate.erase(candidate.size() - 1); candidate.erase(candidate.size() - 1);
val->val.pattern_text_val = util::copy_string(candidate.c_str()); val->val.pattern_text_val = util::copy_string(candidate.c_str(), candidate.size());
break; break;
} }
} }

View file

@ -1022,6 +1022,16 @@ std::string get_escaped_string(const char* str, size_t len, bool escape_all) {
return get_escaped_string(&d, str, len, escape_all)->Description(); return get_escaped_string(&d, str, len, escape_all)->Description();
} }
char* copy_string(const char* str, size_t len) {
if ( ! str )
return nullptr;
char* c = new char[len + 1];
memcpy(c, str, len);
c[len] = '\0';
return c;
}
char* copy_string(const char* s) { char* copy_string(const char* s) {
if ( ! s ) if ( ! s )
return nullptr; return nullptr;

View file

@ -330,6 +330,7 @@ std::vector<std::string>* tokenize_string(std::string_view input, std::string_vi
std::vector<std::string_view> tokenize_string(std::string_view input, const char delim) noexcept; std::vector<std::string_view> tokenize_string(std::string_view input, const char delim) noexcept;
extern char* copy_string(const char* str, size_t len);
extern char* copy_string(const char* s); extern char* copy_string(const char* s);
extern bool streq(const char* s1, const char* s2); extern bool streq(const char* s1, const char* s2);
extern bool starts_with(std::string_view s, std::string_view beginning); extern bool starts_with(std::string_view s, std::string_view beginning);

View file

@ -434,15 +434,14 @@ static std::vector<std::string> get_script_signature_files() {
std::vector<std::string> rval; std::vector<std::string> rval;
// Parse rule files defined on the script level. // Parse rule files defined on the script level.
char* script_signature_files = util::copy_string(id::find_val("signature_files")->AsString()->CheckString()); auto script_signature_files = id::find_val("signature_files")->AsStringVal()->ToStdString();
char* tmp = script_signature_files; char* tmp = script_signature_files.data();
char* s; char* s;
while ( (s = strsep(&tmp, " \t")) ) while ( (s = strsep(&tmp, " \t")) )
if ( *s ) if ( *s )
rval.emplace_back(s); rval.emplace_back(s);
delete[] script_signature_files;
return rval; return rval;
} }

View file

@ -448,7 +448,8 @@ static bool prepare_environment(zeek::TableVal* tbl, bool set)
return false; return false;
} }
char* tmp = zeek::util::copy_string(key->AsString()->CheckString()); auto [data,len] = key->AsString()->CheckStringWithSize();
char* tmp = zeek::util::copy_string(data, len);
zeek::util::to_upper(tmp); zeek::util::to_upper(tmp);
std::string var1 = zeek::util::fmt("ZEEK_ARG_%s", tmp); std::string var1 = zeek::util::fmt("ZEEK_ARG_%s", tmp);
delete [] tmp; delete [] tmp;

View file

@ -439,9 +439,8 @@ vector<string> dir_contents_recursive(string dir) {
while ( dir[dir.size() - 1] == '/' ) while ( dir[dir.size() - 1] == '/' )
dir.erase(dir.size() - 1, 1); dir.erase(dir.size() - 1, 1);
char* dir_copy = util::copy_string(dir.c_str());
char** scan_path = new char*[2]; char** scan_path = new char*[2];
scan_path[0] = dir_copy; scan_path[0] = dir.data();
scan_path[1] = NULL; scan_path[1] = NULL;
FTS* fts = fts_open(scan_path, FTS_NOCHDIR, 0); FTS* fts = fts_open(scan_path, FTS_NOCHDIR, 0);
@ -449,7 +448,6 @@ vector<string> dir_contents_recursive(string dir) {
if ( ! fts ) { if ( ! fts ) {
reporter->Error("fts_open failure: %s", strerror(errno)); reporter->Error("fts_open failure: %s", strerror(errno));
delete[] scan_path; delete[] scan_path;
delete[] dir_copy;
return rval; return rval;
} }
@ -467,7 +465,6 @@ vector<string> dir_contents_recursive(string dir) {
reporter->Error("fts_close failure: %s", strerror(errno)); reporter->Error("fts_close failure: %s", strerror(errno));
delete[] scan_path; delete[] scan_path;
delete[] dir_copy;
return rval; return rval;
} }

View file

@ -73,7 +73,7 @@ zeek::threading::Value* Foo::EntryToVal(zeek::TypeTag type, zeek::TypeTag subtyp
case zeek::TYPE_STRING: { case zeek::TYPE_STRING: {
std::string rnd = RandomString(10); std::string rnd = RandomString(10);
val->val.string_val.data = zeek::util::copy_string(rnd.c_str()); val->val.string_val.data = zeek::util::copy_string(rnd.c_str(), rnd.size());
val->val.string_val.length = rnd.size(); val->val.string_val.length = rnd.size();
break; break;
} }