Skip to content

Commit 25daaa1

Browse files
committed
Support accessing module local vars
+ Add SQLite3 support
1 parent 352e624 commit 25daaa1

File tree

13 files changed

+361
-44
lines changed

13 files changed

+361
-44
lines changed

instrumentation-wasm/src/js_transformer/helpers/insert_code.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,47 @@ fn get_insert_pos(body: &FunctionBody, is_constructor: bool) -> usize {
230230
0 // No super call found, insert at the beginning
231231
}
232232
}
233+
234+
// Add a statement to the end of the body: __instrumentAccessLocalVariables('identifier', [var1, var2]);
235+
pub fn insert_access_local_var<'a>(
236+
allocator: &'a Allocator,
237+
builder: &'a AstBuilder,
238+
identifier: &str,
239+
var_names: &Vec<String>,
240+
body: &mut OxcVec<'a, Statement<'a>>,
241+
) {
242+
let mut instrument_args: OxcVec<'a, Argument<'a>> = builder.vec_with_capacity(2);
243+
244+
// Add the identifier to the arguments
245+
instrument_args.push(Argument::StringLiteral(builder.alloc_string_literal(
246+
SPAN,
247+
allocator.alloc_str(identifier),
248+
None,
249+
)));
250+
251+
// [var1, var2]
252+
let mut array_elements: OxcVec<'a, ArrayExpressionElement<'a>> =
253+
builder.vec_with_capacity(var_names.len());
254+
for name in var_names {
255+
array_elements.push(ArrayExpressionElement::Identifier(
256+
builder.alloc_identifier_reference(SPAN, allocator.alloc_str(name)),
257+
));
258+
}
259+
260+
instrument_args.push(Argument::ArrayExpression(
261+
builder.alloc_array_expression(SPAN, array_elements),
262+
));
263+
264+
// Build and add a call expression
265+
let call_expr = builder.expression_call(
266+
SPAN,
267+
builder.expression_identifier(SPAN, "__instrumentAccessLocalVariables"),
268+
NONE,
269+
instrument_args,
270+
false,
271+
);
272+
273+
let stmt_expression = builder.statement_expression(SPAN, call_expr);
274+
275+
body.push(stmt_expression);
276+
}

instrumentation-wasm/src/js_transformer/helpers/insert_import_statement.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const INSTRUMENT_IMPORT_SOURCE: &str = "@aikidosec/firewall/instrument/internals
1414
const INSTRUMENT_INSPECT_ARGS_METHOD_NAME: &str = "__instrumentInspectArgs";
1515
const INSTRUMENT_MODIFY_ARGS_METHOD_NAME: &str = "__instrumentModifyArgs";
1616
const INSTRUMENT_MODIFY_RETURN_VALUE_METHOD_NAME: &str = "__instrumentModifyReturnValue";
17+
const INSTRUMENT_ACCESS_LOCAL_VARS_METHOD_NAME: &str = "__instrumentAccessLocalVariables";
1718

1819
type ImportMethodPredicate = fn(&FunctionInstructions) -> bool;
1920

@@ -78,6 +79,28 @@ pub fn insert_import_statement<'a>(
7879
}
7980
}
8081

82+
if !file_instructions.access_local_variables.is_empty() {
83+
binding_properties.push(
84+
builder.binding_property(
85+
SPAN,
86+
builder.property_key_static_identifier(
87+
SPAN,
88+
INSTRUMENT_ACCESS_LOCAL_VARS_METHOD_NAME,
89+
),
90+
builder.binding_pattern(
91+
builder.binding_pattern_kind_binding_identifier(
92+
SPAN,
93+
INSTRUMENT_ACCESS_LOCAL_VARS_METHOD_NAME,
94+
),
95+
NONE,
96+
false,
97+
),
98+
true,
99+
false,
100+
),
101+
);
102+
}
103+
81104
if binding_properties.is_empty() {
82105
// If there are no methods to import, we can skip the require statement
83106
return;
@@ -131,6 +154,20 @@ pub fn insert_import_statement<'a>(
131154
}
132155
}
133156

157+
if !file_instructions.access_local_variables.is_empty() {
158+
specifiers.push(
159+
builder.import_declaration_specifier_import_specifier(
160+
SPAN,
161+
builder.module_export_name_identifier_name(
162+
SPAN,
163+
INSTRUMENT_ACCESS_LOCAL_VARS_METHOD_NAME,
164+
),
165+
builder.binding_identifier(SPAN, INSTRUMENT_ACCESS_LOCAL_VARS_METHOD_NAME),
166+
ImportOrExportKind::Value,
167+
),
168+
);
169+
}
170+
134171
if specifiers.is_empty() {
135172
// If there are no methods to import, we can skip the import statement
136173
return;

instrumentation-wasm/src/js_transformer/instructions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ use serde::{Deserialize, Serialize};
44
#[serde(rename_all = "camelCase")]
55
pub struct FileInstructions {
66
pub path: String,
7+
pub identifier: String,
78
pub version_range: String,
89
pub functions: Vec<FunctionInstructions>,
10+
pub access_local_variables: Vec<String>,
911
}
1012

1113
#[derive(Serialize, Deserialize)]

instrumentation-wasm/src/js_transformer/transformer.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use oxc_traverse::traverse_mut;
77

88
use super::{
99
helpers::{
10-
insert_import_statement::insert_import_statement,
10+
insert_code::insert_access_local_var, insert_import_statement::insert_import_statement,
1111
select_sourcetype_based_on_enum::select_sourcetype_based_on_enum,
1212
},
1313
instructions::FileInstructions,
@@ -74,6 +74,16 @@ pub fn transform_code_str(
7474
&file_instructions,
7575
);
7676

77+
if !file_instructions.access_local_variables.is_empty() {
78+
insert_access_local_var(
79+
&allocator,
80+
&ast_builder,
81+
&file_instructions.identifier,
82+
&file_instructions.access_local_variables,
83+
&mut program.body,
84+
);
85+
}
86+
7787
// Todo: Update source map?
7888
let js = Codegen::new()
7989
.with_options(CodegenOptions {

library/agent/hooks/instrumentation/codeTransformation.benchmark.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ t.test("Benchmark: Small code transformation", async (t) => {
4141
{
4242
path: "test.js",
4343
versionRange: "^1.0.0",
44+
identifier: "testpkg.test.js.^1.0.0",
4445
functions: [
4546
{
4647
nodeType: "MethodDefinition",
@@ -52,6 +53,7 @@ t.test("Benchmark: Small code transformation", async (t) => {
5253
modifyArgumentsObject: false,
5354
},
5455
],
56+
accessLocalVariables: [],
5557
}
5658
);
5759
}
@@ -82,7 +84,8 @@ t.test("Benchmark: Large code transformation", async (t) => {
8284

8385
for (let i = 0; i < iterations; i++) {
8486
transformCode("hono", "4.0.0", "dist/hono-base.js", honoSrc, "module", {
85-
path: "dist/hono-base.js-----",
87+
path: "dist/hono-base.js",
88+
identifier: "hono.dist.hono-base.js.v4.0.0",
8689
versionRange: "^4.0.0",
8790
functions: [
8891
{
@@ -95,6 +98,7 @@ t.test("Benchmark: Large code transformation", async (t) => {
9598
modifyArgumentsObject: false,
9699
},
97100
],
101+
accessLocalVariables: [],
98102
});
99103
}
100104

0 commit comments

Comments
 (0)