Skip to content

Commit 79817dc

Browse files
committed
Binary: Extract field references.
1 parent 4378da4 commit 79817dc

3 files changed

Lines changed: 60 additions & 2 deletions

File tree

binary/extractor/cil/Semmle.Extraction.CSharp.IL/ILExtractor.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ private void ExtractType(TypeDefinition type) {
8585
ExtractMethod(method, typeId);
8686
}
8787

88+
// Extract fields
89+
foreach (var field in type.Fields) {
90+
var fieldId = trap.GetId();
91+
ExtractField(field, typeId);
92+
}
93+
8894
// Extract nested types (includes compiler-generated state machines)
8995
if (type.HasNestedTypes) {
9096
foreach (var nestedType in type.NestedTypes) {
@@ -125,6 +131,11 @@ private void ExtractMethod(MethodDefinition method, int typeId) {
125131
}
126132
}
127133

134+
private void ExtractField(FieldDefinition field, int typeId) {
135+
var fieldId = trap.GetId();
136+
trap.WriteTuple("fields", fieldId, field.Name, typeId);
137+
}
138+
128139
private void ExtractMethodBody(MethodDefinition method, int methodId) {
129140
var body = method.Body;
130141

@@ -174,6 +185,9 @@ private void ExtractMethodBody(MethodDefinition method, int methodId) {
174185
} else if (instruction.Operand is VariableDefinition varDef) {
175186
// Local variable reference (ldloc, stloc, ldloca)
176187
trap.WriteTuple("il_operand_local_index", instrId, varDef.Index);
188+
} else if (instruction.Operand is FieldReference fieldRef) {
189+
var declaringTypeName = fieldRef.DeclaringType.FullName.Replace('/', '.');
190+
trap.WriteTuple("il_field_operand", instrId, declaringTypeName, fieldRef.Name);
177191
} else if (instruction.Operand is string str) {
178192
trap.WriteTuple("il_operand_string", instrId, str);
179193
} else if (instruction.Operand is sbyte sb) {

binary/ql/lib/semmle/code/binary/ast/internal/CilInstructions.qll

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
private import binary
22

3+
class CilField extends @field {
4+
string toString() { result = this.getName() }
5+
6+
string getName() { fields(this, result, _) }
7+
8+
CilType getDeclaringType() { fields(this, _, result) }
9+
10+
Location getLocation() { none() } // TODO: Extract
11+
}
12+
313
/**
414
* A CIL type (class, struct, interface, etc.).
515
*/
@@ -18,6 +28,9 @@ class CilType extends @type {
1828
/** Gets a method declared in this type. */
1929
CilMethod getAMethod() { result.getDeclaringType() = this }
2030

31+
/** Gets a field declared by this type. */
32+
CilField getAField() { result.getDeclaringType() = this }
33+
2134
Location getLocation() { none() } // TODO: Extract
2235
}
2336

@@ -625,14 +638,33 @@ class CilLdsfld extends @il_ldsfld, CilLoadFieldInstruction { }
625638
/** An instruction that loads the address of a static field. */
626639
class CilLdsflda extends @il_ldsflda, CilLoadFieldInstruction { }
627640

641+
pragma[nomagic]
642+
private predicate fieldHasDeclaringTypeNameAndName(
643+
string declaringTypeName, string fieldName, CilField f
644+
) {
645+
f.getDeclaringType().getFullName() = declaringTypeName and
646+
f.getName() = fieldName
647+
}
648+
628649
/** An instruction that stores a value to a field. */
629-
abstract class CilStoreFieldInstruction extends CilInstruction { }
650+
abstract class CilStoreFieldInstruction extends CilInstruction {
651+
CilField getField() {
652+
exists(string declaringTypeName, string fieldName |
653+
il_field_operand(this, declaringTypeName, fieldName) and
654+
fieldHasDeclaringTypeNameAndName(declaringTypeName, fieldName, result)
655+
)
656+
}
657+
658+
predicate isStatic() { none() }
659+
}
630660

631661
/** An instruction that stores a value to an instance field. */
632662
class CilStfld extends @il_stfld, CilStoreFieldInstruction { }
633663

634664
/** An instruction that stores a value to a static field. */
635-
class CilStsfld extends @il_stsfld, CilStoreFieldInstruction { }
665+
class CilStsfld extends @il_stsfld, CilStoreFieldInstruction {
666+
final override predicate isStatic() { any() }
667+
}
636668

637669
class CilStobj extends @il_stobj, CilInstruction { }
638670

binary/ql/lib/semmlecode.binary.dbscheme

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,6 +2141,12 @@ methods(
21412141
int type_id: @type ref
21422142
);
21432143

2144+
fields(
2145+
unique int id: @field,
2146+
string name: string ref,
2147+
int type_id: @type ref
2148+
);
2149+
21442150
case @il_instruction.mnemonic of
21452151
0 = @il_nop
21462152
| 1 = @il_break
@@ -2438,6 +2444,12 @@ il_call_target_unresolved(
24382444
string target_method_name: string ref
24392445
);
24402446

2447+
il_field_operand(
2448+
int instruction: @il_instruction ref,
2449+
string declaring_type_name: string ref,
2450+
string field_name: string ref
2451+
);
2452+
24412453
/**
24422454
* String operands for IL instructions.
24432455
* Used for ldstr (load string) instructions.

0 commit comments

Comments
 (0)