Skip to content

Commit 872d9a5

Browse files
committed
Extract and model CIL local variables and float/double operands
Adds extraction of local variables and their types from CIL method bodies, and models their usage in QL. Also extracts float and double operands for IL instructions and updates the QL schema and extractor to support these features. Enhances QL classes to provide access to local variables and their indices, and supports float/double constant values in instructions.
1 parent 12c61e2 commit 872d9a5

3 files changed

Lines changed: 106 additions & 12 deletions

File tree

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,15 @@ private void ExtractMethod(MethodDefinition method, int typeId) {
108108
private void ExtractMethodBody(MethodDefinition method, int methodId) {
109109
var body = method.Body;
110110

111+
// Extract local variables
112+
if (body.HasVariables) {
113+
foreach (var variable in body.Variables) {
114+
var varId = trap.GetId();
115+
trap.WriteTuple("il_local_variable", varId, methodId, variable.Index,
116+
variable.VariableType.FullName);
117+
}
118+
}
119+
111120
// Write each IL instruction
112121
var index = 0;
113122
foreach (var instruction in body.Instructions) {
@@ -142,6 +151,9 @@ private void ExtractMethodBody(MethodDefinition method, int methodId) {
142151
if(methodRef.MethodReturnType.ReturnType.MetadataType is not Mono.Cecil.MetadataType.Void) {
143152
trap.WriteTuple("il_call_has_return_value", instrId);
144153
}
154+
} else if (instruction.Operand is VariableDefinition varDef) {
155+
// Local variable reference (ldloc, stloc, ldloca)
156+
trap.WriteTuple("il_operand_local_index", instrId, varDef.Index);
145157
} else if (instruction.Operand is string str) {
146158
trap.WriteTuple("il_operand_string", instrId, str);
147159
} else if (instruction.Operand is sbyte sb) {
@@ -152,6 +164,10 @@ private void ExtractMethodBody(MethodDefinition method, int methodId) {
152164
trap.WriteTuple("il_operand_int", instrId, i);
153165
} else if (instruction.Operand is long l) {
154166
trap.WriteTuple("il_operand_long", instrId, l);
167+
} else if (instruction.Operand is float f) {
168+
trap.WriteTuple("il_operand_float", instrId, f);
169+
} else if (instruction.Operand is double d) {
170+
trap.WriteTuple("il_operand_double", instrId, d);
155171
}
156172

157173
index++;

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

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
private import binary
22

3-
// TODO
4-
class CilVariable instanceof @method {
5-
string toString() { none() }
3+
/** A local variable defined in a CIL method body. */
4+
class CilVariable extends @il_local_variable {
5+
string toString() { result = "local_" + this.getIndex().toString() }
6+
7+
/** Gets the method that defines this local variable. */
8+
CilMethod getMethod() { il_local_variable(this, result, _, _) }
9+
10+
/** Gets the index of this local variable in the method's local variable list. */
11+
int getIndex() { il_local_variable(this, _, result, _) }
12+
13+
/** Gets the type name of this local variable. */
14+
string getTypeName() { il_local_variable(this, _, _, result) }
615
}
716

817
class CilParameter instanceof @il_parameter {
@@ -30,7 +39,11 @@ class CilMethod extends @method {
3039

3140
CilInstruction getInstruction(int i) { il_instruction_parent(result, i, this) }
3241

33-
CilVariable getVariable(int i) { none() } // TODO
42+
/** Gets the local variable at the given index in this method. */
43+
CilVariable getVariable(int i) {
44+
result.getMethod() = this and
45+
result.getIndex() = i
46+
}
3447

3548
CilParameter getParameter(int i) {
3649
result.getMethod() = this and
@@ -156,21 +169,36 @@ class CilStarg_S extends @il_starg_S, CilStoreArgument { }
156169

157170
class CilLdloc_S extends @il_ldloc_S, CilLoadLocal {
158171
override int getLocalVariableIndex() {
159-
none() // TODO: Extract
172+
il_operand_local_index(this, result)
160173
}
161174
}
162175

163176
abstract class CilLoadLocal extends CilInstruction {
164177
abstract int getLocalVariableIndex();
178+
179+
/** Gets the local variable that this instruction loads. */
180+
CilVariable getLocalVariable() {
181+
result = this.getEnclosingMethod().getVariable(this.getLocalVariableIndex())
182+
}
165183
}
166184

167-
abstract class CilLoadAddressOfLocal extends CilInstruction { }
185+
abstract class CilLoadAddressOfLocal extends CilInstruction {
186+
/** Gets the local variable index. */
187+
int getLocalVariableIndex() {
188+
il_operand_local_index(this, result)
189+
}
190+
191+
/** Gets the local variable whose address this instruction loads. */
192+
CilVariable getLocalVariable() {
193+
result = this.getEnclosingMethod().getVariable(this.getLocalVariableIndex())
194+
}
195+
}
168196

169197
class CilLdloca_S extends @il_ldloca_S, CilLoadAddressOfLocal { }
170198

171199
class CilStloc_S extends @il_stloc_S, CilStoreLocal {
172200
override int getLocalVariableIndex() {
173-
none() // TODO: Extract
201+
il_operand_local_index(this, result)
174202
}
175203
}
176204

@@ -279,17 +307,29 @@ class CilLdc_I8 extends @il_ldc_I8, CilLoadConstant {
279307

280308
class CilLdc_R4 extends @il_ldc_R4, CilLoadConstant {
281309
final override string getValue() {
282-
none() // TODO
310+
exists(float f |
311+
il_operand_float(this, f) and
312+
result = f.toString()
313+
)
283314
}
284315

316+
/** Gets the float value loaded by this instruction. */
317+
float getFloatValue() { il_operand_float(this, result) }
318+
285319
final override int getSize() { result = 4 } // float32
286320
}
287321

288322
class CilLdc_R8 extends @il_ldc_R8, CilLoadConstant {
289323
final override string getValue() {
290-
none() // TODO
324+
exists(float d |
325+
il_operand_double(this, d) and
326+
result = d.toString()
327+
)
291328
}
292329

330+
/** Gets the double value loaded by this instruction. */
331+
float getDoubleValue() { il_operand_double(this, result) }
332+
293333
final override int getSize() { result = 8 } // float64
294334
}
295335

@@ -741,11 +781,11 @@ class CilStarg extends @il_starg, CilInstruction { }
741781

742782
class CilLdloc extends @il_ldloc, CilLoadLocal {
743783
override int getLocalVariableIndex() {
744-
none() // TODO: Extract
784+
il_operand_local_index(this, result)
745785
}
746786
}
747787

748-
class CilLdloca extends @il_ldloca, CilInstruction { }
788+
class CilLdloca extends @il_ldloca, CilLoadAddressOfLocal { }
749789

750790
abstract class CilStoreLocal extends CilInstruction {
751791
abstract int getLocalVariableIndex();
@@ -757,7 +797,7 @@ abstract class CilStoreLocal extends CilInstruction {
757797

758798
class CilStloc extends @il_stloc, CilStoreLocal {
759799
override int getLocalVariableIndex() {
760-
none() // TODO: Extract
800+
il_operand_local_index(this, result)
761801
}
762802
}
763803

binary/ql/lib/semmlecode.binary.dbscheme

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,44 @@ il_operand_long(
24752475
int value: int ref
24762476
);
24772477

2478+
/**
2479+
* Float operands for IL instructions.
2480+
* Used for ldc.r4 (load constant float32) instructions.
2481+
*/
2482+
il_operand_float(
2483+
int instruction: @il_instruction ref,
2484+
float value: float ref
2485+
);
2486+
2487+
/**
2488+
* Double operands for IL instructions.
2489+
* Used for ldc.r8 (load constant float64) instructions.
2490+
*/
2491+
il_operand_double(
2492+
int instruction: @il_instruction ref,
2493+
float value: float ref
2494+
);
2495+
2496+
/**
2497+
* Local variable index operands for IL instructions.
2498+
* Used for ldloc, stloc, ldloca instructions that reference local variables.
2499+
*/
2500+
il_operand_local_index(
2501+
int instruction: @il_instruction ref,
2502+
int index: int ref
2503+
);
2504+
2505+
/**
2506+
* Local variables defined in method bodies.
2507+
* Each local variable has an index and a type.
2508+
*/
2509+
il_local_variable(
2510+
unique int id: @il_local_variable,
2511+
int method: @method ref,
2512+
int index: int ref,
2513+
string type_name: string ref
2514+
);
2515+
24782516
/**
24792517
* Exception handlers (try/catch/finally blocks) in methods.
24802518
* Each handler represents a try block with its associated catch/finally/fault handler.

0 commit comments

Comments
 (0)