Skip to content

Commit 9831637

Browse files
fixed private rule definitions
added issue #32 test added isrulestart and isruleend helpers
1 parent 5056c8d commit 9831637

File tree

4 files changed

+60
-7
lines changed

4 files changed

+60
-7
lines changed

test/extension.test.ts

+30
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,34 @@ suite("YARA: Provider", function () {
227227
}
228228
});
229229
});
230+
231+
/*
232+
Trying to capture definitions for private rules
233+
Should align symbol `my_private_rule` with definition started by `private rule my_private_rule`
234+
*/
235+
test("issue #32", function (done) {
236+
const filepath: string = path.join(workspace, "private_rule_goto.yara");
237+
vscode.workspace.openTextDocument(filepath).then(function (doc) {
238+
const defProvider: vscode.DefinitionProvider = new YaraDefinitionProvider();
239+
// my_private_rule: Line 10, Col 14
240+
let pos: vscode.Position = new vscode.Position(9, 14);
241+
let tokenSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
242+
let result = defProvider.provideDefinition(doc, pos, tokenSource.token);
243+
if (result instanceof vscode.Location) {
244+
let resultWordRange: vscode.Range = doc.getWordRangeAtPosition(result.range.start);
245+
let resultWord: string = doc.getText(resultWordRange);
246+
if (resultWord == "my_private_rule" && resultWordRange.start.line == 0 && resultWordRange.start.character == 13) { done(); }
247+
}
248+
else if (result instanceof Array) {
249+
// Should only get one result, so we've failed if an Array is returned
250+
}
251+
else if (result instanceof Promise) {
252+
result.then(function (definition) {
253+
let resultWordRange: vscode.Range = doc.getWordRangeAtPosition(definition.range.start);
254+
let resultWord: string = doc.getText(resultWordRange);
255+
if (resultWord == "my_private_rule" && resultWordRange.start.line == 0 && resultWordRange.start.character == 13) { done(); }
256+
});
257+
}
258+
});
259+
});
230260
});

test/rules/private_rule_goto.yara

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
private rule my_private_rule
2+
{
3+
condition:
4+
true
5+
}
6+
7+
rule my_public_rule
8+
{
9+
condition:
10+
my_private_rule
11+
}

yara/src/definitionProvider.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use strict";
22

33
import * as vscode from "vscode";
4-
import {GetRuleRange, varFirstChar} from "./helpers";
4+
import {GetRuleRange, varFirstChar, IsRuleStart} from "./helpers";
55

66

77
export class YaraDefinitionProvider implements vscode.DefinitionProvider {
@@ -34,7 +34,7 @@ export class YaraDefinitionProvider implements vscode.DefinitionProvider {
3434
else {
3535
for (let lineNo = 0; lineNo < pos.line; lineNo++) {
3636
let character: number = lines[lineNo].indexOf(symbol);
37-
if (character != -1 && lines[lineNo].startsWith("rule")) {
37+
if (character != -1 && IsRuleStart(lines[lineNo])) {
3838
// console.log(`Found ${symbol} on line ${lineNo} at character ${character}`);
3939
let defPosition: vscode.Position = new vscode.Position(lineNo, character);
4040
definition = new vscode.Location(fileUri, defPosition);

yara/src/helpers.ts

+17-5
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,34 @@ export const varFirstChar: Set<string> = new Set(["$", "#", "@", "!"]);
1212
export function GetRuleRange(lines: string[], symbol: vscode.Position) {
1313
let begin: vscode.Position | null = null;
1414
let end: vscode.Position | null = null;
15-
const startRuleRegexp = RegExp("^rule ");
16-
const endRuleRegexp = RegExp("^\}");
1715
// find the nearest reference to "rule" by traversing the lines in reverse order
1816
for (let lineNo = symbol.line; lineNo >= 0; lineNo--) {
19-
if (startRuleRegexp.test(lines[lineNo])) {
17+
if (IsRuleStart(lines[lineNo])) {
2018
begin = new vscode.Position(lineNo, 0);
2119
break;
2220
}
2321
}
2422
// start up this loop again using the beginning of the rule
2523
// and find the line with just a curly brace to identify the end of a rule
2624
for (let lineNo = begin.line; lineNo < lines.length; lineNo++) {
27-
if (endRuleRegexp.test(lines[lineNo])) {
25+
if (IsRuleEnd(lines[lineNo])) {
2826
end = new vscode.Position(lineNo, 0);
2927
break;
3028
}
3129
}
3230
return new vscode.Range(begin, end);
33-
}
31+
}
32+
33+
/*
34+
Determine if the given line is the start of a YARA rule or not
35+
*/
36+
export function IsRuleStart(line: string) {
37+
return new RegExp("^(private )?rule ").test(line);
38+
}
39+
40+
/*
41+
Determine if the given line is the end of a YARA rule or not
42+
*/
43+
export function IsRuleEnd(line: string) {
44+
return new RegExp("^\}").test(line);
45+
}

0 commit comments

Comments
 (0)