-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add propagation string case functions and Array.join function (#98)
* String case operations * Array join operator * Fix lint * Fix cpp-lint * Fix cpp-lint * Additional tests for Array.join * Fix test denomination * Fix arguments count * Extract variables * Proper initialization of newRanges for array join * Remove unnecessary conditional * Additional test for String case * Fix lint * Fix to avoid SegFault when checking new ranges * Fix lint
- Loading branch information
Showing
10 changed files
with
771 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/** | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc. | ||
**/ | ||
#include <new> | ||
#include <vector> | ||
#include <memory> | ||
#include <string> | ||
|
||
#include "array_join.h" | ||
#include "../tainted/range.h" | ||
#include "../tainted/string_resource.h" | ||
#include "../tainted/transaction.h" | ||
#include "../iast.h" | ||
|
||
using v8::FunctionCallbackInfo; | ||
using v8::Value; | ||
using v8::Local; | ||
using v8::Isolate; | ||
using v8::Object; | ||
using v8::String; | ||
|
||
using iast::tainted::Range; | ||
|
||
namespace iast { | ||
namespace api { | ||
|
||
const int DEFAULT_JOIN_SEPARATOR_LENGTH = 1; | ||
|
||
void copyRangesWithOffset(Transaction* transaction, | ||
SharedRanges* origRanges, | ||
SharedRanges** destRanges, | ||
int offset) { | ||
if (origRanges != nullptr) { | ||
auto end = origRanges->end(); | ||
for (auto it = origRanges->begin(); it != end; it++) { | ||
auto origRange = *it; | ||
auto newRange = transaction->GetRange( | ||
origRange->start + offset, | ||
origRange->end + offset, | ||
origRange->inputInfo, | ||
origRange->secureMarks); | ||
|
||
if (newRange != nullptr) { | ||
if (*destRanges == nullptr) { | ||
*destRanges = transaction->GetSharedVectorRange(); | ||
} | ||
(*destRanges)->PushBack(newRange); | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
SharedRanges* getJoinResultRanges(Isolate* isolate, | ||
Transaction* transaction, v8::Array* arr, | ||
SharedRanges* separatorRanges, | ||
int separatorLength) { | ||
auto length = arr->Length(); | ||
int offset = 0; | ||
SharedRanges* newRanges = nullptr; | ||
auto context = isolate->GetCurrentContext(); | ||
for (uint32_t i = 0; i < length; i++) { | ||
if (i > 0) { | ||
copyRangesWithOffset(transaction, separatorRanges, &newRanges, offset); | ||
offset += separatorLength; | ||
} | ||
auto maybeItem = arr->Get(context, i); | ||
if (!maybeItem.IsEmpty()) { | ||
auto item = maybeItem.ToLocalChecked(); | ||
auto taintedItem = transaction->FindTaintedObject(utils::GetLocalPointer(item)); | ||
auto itemRanges = taintedItem ? taintedItem->getRanges() : nullptr; | ||
copyRangesWithOffset(transaction, itemRanges, &newRanges, offset); | ||
offset += utils::GetLength(isolate, item); | ||
} | ||
} | ||
|
||
return newRanges; | ||
} | ||
|
||
void ArrayJoinOperator(const FunctionCallbackInfo<Value>& args) { | ||
auto isolate = args.GetIsolate(); | ||
|
||
if (args.Length() < 3) { | ||
isolate->ThrowException(v8::Exception::TypeError( | ||
v8::String::NewFromUtf8(isolate, | ||
"Wrong number of arguments", | ||
v8::NewStringType::kNormal).ToLocalChecked())); | ||
return; | ||
} | ||
|
||
auto result = args[1]; | ||
|
||
if (!result->IsString()) { | ||
args.GetReturnValue().Set(result); | ||
return; | ||
} | ||
|
||
auto transaction = GetTransaction(utils::GetLocalPointer(args[0])); | ||
if (transaction == nullptr) { | ||
args.GetReturnValue().Set(result); | ||
return; | ||
} | ||
|
||
auto thisArg = args[2]; | ||
if (thisArg->IsObject()) { | ||
auto arrObj = v8::Object::Cast(*thisArg); | ||
if (arrObj->IsArray()) { | ||
try { | ||
int separatorLength = DEFAULT_JOIN_SEPARATOR_LENGTH; | ||
SharedRanges* separatorRanges = nullptr; | ||
if (args.Length() > 3) { | ||
auto separatorArg = args[3]; | ||
auto separatorValue = (*separatorArg); | ||
if (!separatorValue->IsUndefined()) { | ||
auto taintedSeparator = transaction->FindTaintedObject(utils::GetLocalPointer(separatorArg)); | ||
separatorRanges = taintedSeparator ? taintedSeparator->getRanges() : nullptr; | ||
separatorLength = utils::GetCoercedLength(isolate, separatorArg); | ||
} | ||
} | ||
auto arr = v8::Array::Cast(arrObj); | ||
|
||
auto newRanges = getJoinResultRanges(isolate, transaction, arr, separatorRanges, separatorLength); | ||
if (newRanges != nullptr) { | ||
auto key = utils::GetLocalPointer(result); | ||
transaction->AddTainted(key, newRanges, result); | ||
args.GetReturnValue().Set(result); | ||
return; | ||
} | ||
} catch (const std::bad_alloc& err) { | ||
} catch (const container::QueuedPoolBadAlloc& err) { | ||
} catch (const container::PoolBadAlloc& err) { | ||
} | ||
} | ||
} | ||
args.GetReturnValue().Set(args[1]); | ||
} | ||
|
||
void ArrayJoinOperations::Init(Local<Object> exports) { | ||
NODE_SET_METHOD(exports, "arrayJoin", ArrayJoinOperator); | ||
} | ||
} // namespace api | ||
} // namespace iast | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc. | ||
**/ | ||
#ifndef SRC_API_ARRAY_JOIN_H_ | ||
#define SRC_API_ARRAY_JOIN_H_ | ||
|
||
#include <node.h> | ||
namespace iast { | ||
namespace api { | ||
class ArrayJoinOperations { | ||
public: | ||
static void Init(v8::Local<v8::Object> exports); | ||
|
||
private: | ||
ArrayJoinOperations(); | ||
~ArrayJoinOperations(); | ||
}; | ||
} // namespace api | ||
} // namespace iast | ||
#endif // SRC_API_ARRAY_JOIN_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/** | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc. | ||
**/ | ||
#include <new> | ||
#include <vector> | ||
#include <memory> | ||
#include <string> | ||
|
||
#include "string_case.h" | ||
#include "../tainted/range.h" | ||
#include "../tainted/string_resource.h" | ||
#include "../tainted/transaction.h" | ||
#include "../iast.h" | ||
|
||
#define TO_V8STRING(arg) (v8::Local<v8::String>::Cast(arg)) | ||
|
||
using v8::FunctionCallbackInfo; | ||
using v8::Value; | ||
using v8::Local; | ||
using v8::Isolate; | ||
using v8::Object; | ||
using v8::String; | ||
|
||
using iast::tainted::Range; | ||
|
||
namespace iast { | ||
namespace api { | ||
|
||
void StringCaseOperator(const FunctionCallbackInfo<Value>& args) { | ||
auto isolate = args.GetIsolate(); | ||
|
||
if (args.Length() < 3) { | ||
isolate->ThrowException(v8::Exception::TypeError( | ||
v8::String::NewFromUtf8(isolate, | ||
"Wrong number of arguments", | ||
v8::NewStringType::kNormal).ToLocalChecked())); | ||
return; | ||
} | ||
if (!args[1]->IsString()) { | ||
args.GetReturnValue().Set(args[1]); | ||
return; | ||
} | ||
|
||
auto transaction = GetTransaction(utils::GetLocalPointer(args[0])); | ||
if (transaction == nullptr) { | ||
args.GetReturnValue().Set(args[1]); | ||
return; | ||
} | ||
|
||
if (args[1] == args[2]) { | ||
args.GetReturnValue().Set(args[1]); | ||
return; | ||
} | ||
|
||
auto taintedObj = transaction->FindTaintedObject(utils::GetLocalPointer(args[2])); | ||
if (!taintedObj) { | ||
args.GetReturnValue().Set(args[1]); | ||
return; | ||
} | ||
|
||
try { | ||
auto ranges = taintedObj->getRanges(); | ||
if (ranges == nullptr) { | ||
args.GetReturnValue().Set(args[1]); | ||
return; | ||
} | ||
|
||
auto res = args[1]; | ||
int resultLength = TO_V8STRING(res)->Length(); | ||
if (resultLength == 1) { | ||
res = tainted::NewExternalString(isolate, res); | ||
} | ||
auto key = utils::GetLocalPointer(res); | ||
transaction->AddTainted(key, ranges, res); | ||
args.GetReturnValue().Set(res); | ||
return; | ||
} catch (const std::bad_alloc& err) { | ||
} catch (const container::QueuedPoolBadAlloc& err) { | ||
} catch (const container::PoolBadAlloc& err) { | ||
} | ||
args.GetReturnValue().Set(args[1]); | ||
} | ||
|
||
void StringCaseOperations::Init(Local<Object> exports) { | ||
NODE_SET_METHOD(exports, "stringCase", StringCaseOperator); | ||
} | ||
} // namespace api | ||
} // namespace iast | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/** | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc. | ||
**/ | ||
#ifndef SRC_API_STRING_CASE_H_ | ||
#define SRC_API_STRING_CASE_H_ | ||
|
||
#include <node.h> | ||
namespace iast { | ||
namespace api { | ||
class StringCaseOperations { | ||
public: | ||
static void Init(v8::Local<v8::Object> exports); | ||
|
||
private: | ||
StringCaseOperations(); | ||
~StringCaseOperations(); | ||
}; | ||
} // namespace api | ||
} // namespace iast | ||
#endif // SRC_API_STRING_CASE_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.