Skip to content

Commit 3a5140c

Browse files
committed
Indexers and events
Added test for indexers. Added support for event accesses and added test.
1 parent 16d8d2e commit 3a5140c

File tree

5 files changed

+236
-0
lines changed

5 files changed

+236
-0
lines changed

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ private predicate ignoreExprOnly(Expr expr) {
9999
// Ignore the expression (that is not a declaration)
100100
// that appears in a using block
101101
expr.getParent().(UsingBlockStmt).getExpr() = expr
102+
or
103+
// Ignore the `ThisAccess` when it is used as the qualifier for
104+
// a callable access (e.g. when a member callable is passed as a
105+
// parameter for a delegate creation expression)
106+
expr instanceof ThisAccess and
107+
expr.getParent() instanceof CallableAccess
102108
}
103109

104110
/**

csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/TranslatedExpr.qll

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,11 @@ class TranslatedAssignExpr extends TranslatedAssignment {
13821382
class TranslatedAssignOperation extends TranslatedAssignment {
13831383
override AssignOperation expr;
13841384

1385+
TranslatedAssignOperation() {
1386+
// Assignments to events is handled differently
1387+
not expr.getLValue() instanceof EventAccess
1388+
}
1389+
13851390
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
13861391
kind instanceof GotoEdge and
13871392
(
@@ -2057,3 +2062,37 @@ class TranslatedDelegateCreation extends TranslatedCreation {
20572062

20582063
override predicate needsLoad() { none() }
20592064
}
2065+
2066+
/**
2067+
* Represents the IR translation of an assign operation where the lhs is an event access.
2068+
*/
2069+
class TranslatedEventAccess extends TranslatedNonConstantExpr {
2070+
override AssignOperation expr;
2071+
2072+
TranslatedEventAccess() { expr.getLValue() instanceof EventAccess }
2073+
2074+
// We only translate the lhs, since the rhs is translated as part of the
2075+
// accessor call.
2076+
override TranslatedElement getChild(int id) { id = 0 and result = this.getLValue() }
2077+
2078+
override predicate hasInstruction(
2079+
Opcode opcode, InstructionTag tag, Type resultType, boolean isLValue
2080+
) {
2081+
none()
2082+
}
2083+
2084+
final override Instruction getFirstInstruction() {
2085+
result = this.getLValue().getFirstInstruction()
2086+
}
2087+
2088+
override Instruction getResult() { none() }
2089+
2090+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
2091+
2092+
override Instruction getChildSuccessor(TranslatedElement child) {
2093+
child = this.getLValue() and
2094+
result = this.getParent().getChildSuccessor(this)
2095+
}
2096+
2097+
private TranslatedExpr getLValue() { result = getTranslatedExpr(expr.getLValue()) }
2098+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class Events
2+
{
3+
public delegate string MyDel(string str);
4+
5+
event MyDel MyEvent;
6+
7+
public Events() {
8+
this.MyEvent += new MyDel(this.WelcomeUser);
9+
}
10+
11+
public string WelcomeUser(string username) {
12+
return "Welcome " + username;
13+
}
14+
15+
static void Main(string[] args) {
16+
Events obj1 = new Events();
17+
string result = obj1.MyEvent("Tutorials Point");
18+
}
19+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
class Indexers
2+
{
3+
public class Contact
4+
{
5+
private string[] address = new string[3];
6+
public string this[int index]
7+
{
8+
get
9+
{
10+
return address[index];
11+
}
12+
set
13+
{
14+
address[index] = value;
15+
}
16+
}
17+
}
18+
19+
public static void Main()
20+
{
21+
Contact contact = new Contact();
22+
contact[0] = "Begumpet";
23+
contact[1] = "Hyderabad";
24+
contact[2] = "Telengana";
25+
}
26+
}

csharp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,70 @@ delegates.cs:
480480
# 11| v0_17(Void) = UnmodeledUse : mu*
481481
# 11| v0_18(Void) = ExitFunction :
482482

483+
events.cs:
484+
# 7| System.Void Events..ctor()
485+
# 7| Block 0
486+
# 7| v0_0(Void) = EnterFunction :
487+
# 7| mu0_1(null) = AliasedDefinition :
488+
# 7| mu0_2(null) = UnmodeledDefinition :
489+
# 7| r0_3(glval<Events>) = InitializeThis :
490+
# 8| r0_4(Events) = CopyValue : r0_3
491+
# 8| r0_5(glval<null>) = FunctionAddress[add_MyEvent] :
492+
# 8| r0_6(MyDel) = NewObj :
493+
# 8| r0_7(glval<null>) = FunctionAddress[MyDel] :
494+
# 8| r0_8(glval<MyDel>) = FunctionAddress[WelcomeUser] :
495+
# 8| v0_9(Void) = Call : func:r0_7, this:r0_6, 0:r0_8
496+
# 8| mu0_10(null) = ^CallSideEffect : ~mu0_2
497+
# 8| v0_11(Void) = Call : func:r0_5, this:r0_4, 0:r0_6
498+
# 8| mu0_12(null) = ^CallSideEffect : ~mu0_2
499+
# 7| v0_13(Void) = ReturnVoid :
500+
# 7| v0_14(Void) = UnmodeledUse : mu*
501+
# 7| v0_15(Void) = ExitFunction :
502+
503+
# 11| System.String Events.WelcomeUser(System.String)
504+
# 11| Block 0
505+
# 11| v0_0(Void) = EnterFunction :
506+
# 11| mu0_1(null) = AliasedDefinition :
507+
# 11| mu0_2(null) = UnmodeledDefinition :
508+
# 11| r0_3(glval<Events>) = InitializeThis :
509+
# 11| r0_4(glval<String>) = VariableAddress[username] :
510+
# 11| mu0_5(String) = InitializeParameter[username] : &:r0_4
511+
# 12| r0_6(glval<String>) = VariableAddress[#return] :
512+
# 12| r0_7(String) = StringConstant["Welcome "] :
513+
# 12| r0_8(glval<String>) = VariableAddress[username] :
514+
# 12| r0_9(String) = Load : &:r0_8, ~mu0_2
515+
# 12| r0_10(String) = Add : r0_7, r0_9
516+
# 12| mu0_11(String) = Store : &:r0_6, r0_10
517+
# 11| r0_12(glval<String>) = VariableAddress[#return] :
518+
# 11| v0_13(Void) = ReturnValue : &:r0_12, ~mu0_2
519+
# 11| v0_14(Void) = UnmodeledUse : mu*
520+
# 11| v0_15(Void) = ExitFunction :
521+
522+
# 15| System.Void Events.Main(System.String[])
523+
# 15| Block 0
524+
# 15| v0_0(Void) = EnterFunction :
525+
# 15| mu0_1(null) = AliasedDefinition :
526+
# 15| mu0_2(null) = UnmodeledDefinition :
527+
# 15| r0_3(glval<String[]>) = VariableAddress[args] :
528+
# 15| mu0_4(String[]) = InitializeParameter[args] : &:r0_3
529+
# 16| r0_5(glval<Events>) = VariableAddress[obj1] :
530+
# 16| r0_6(Events) = NewObj :
531+
# 16| r0_7(glval<null>) = FunctionAddress[Events] :
532+
# 16| v0_8(Void) = Call : func:r0_7, this:r0_6
533+
# 16| mu0_9(null) = ^CallSideEffect : ~mu0_2
534+
# 16| mu0_10(Events) = Store : &:r0_5, r0_6
535+
# 17| r0_11(glval<String>) = VariableAddress[result] :
536+
# 17| r0_12(glval<Events>) = VariableAddress[obj1] :
537+
# 17| r0_13(Events) = Load : &:r0_12, ~mu0_2
538+
# 17| r0_14(glval<null>) = FunctionAddress[Invoke] :
539+
# 17| r0_15(String) = StringConstant["Tutorials Point"] :
540+
# 17| v0_16(Void) = Call : func:r0_14, this:r0_13, 0:r0_15
541+
# 17| mu0_17(null) = ^CallSideEffect : ~mu0_2
542+
# 17| mu0_18(String) = Store : &:r0_11, v0_16
543+
# 15| v0_19(Void) = ReturnVoid :
544+
# 15| v0_20(Void) = UnmodeledUse : mu*
545+
# 15| v0_21(Void) = ExitFunction :
546+
483547
foreach.cs:
484548
# 4| System.Void ForEach.Main()
485549
# 4| Block 0
@@ -598,6 +662,88 @@ func_with_param_call.cs:
598662
# 10| v0_12(Void) = UnmodeledUse : mu*
599663
# 10| v0_13(Void) = ExitFunction :
600664

665+
indexers.cs:
666+
# 8| System.String Indexers.Contact.get_Item(System.Int32)
667+
# 8| Block 0
668+
# 8| v0_0(Void) = EnterFunction :
669+
# 8| mu0_1(null) = AliasedDefinition :
670+
# 8| mu0_2(null) = UnmodeledDefinition :
671+
# 8| r0_3(glval<Contact>) = InitializeThis :
672+
# 6| r0_4(glval<Int32>) = VariableAddress[index] :
673+
# 6| mu0_5(Int32) = InitializeParameter[index] : &:r0_4
674+
# 10| r0_6(glval<String>) = VariableAddress[#return] :
675+
# 10| r0_7(Contact) = CopyValue : r0_3
676+
# 10| r0_8(glval<String[]>) = FieldAddress[address] : r0_7
677+
# 10| r0_9(String[]) = ElementsAddress : r0_8
678+
# 10| r0_10(glval<Int32>) = VariableAddress[index] :
679+
# 10| r0_11(Int32) = Load : &:r0_10, ~mu0_2
680+
# 10| r0_12(String[]) = PointerAdd[4] : r0_9, r0_11
681+
# 10| r0_13(String) = Load : &:r0_12, ~mu0_2
682+
# 10| mu0_14(String) = Store : &:r0_6, r0_13
683+
# 8| r0_15(glval<String>) = VariableAddress[#return] :
684+
# 8| v0_16(Void) = ReturnValue : &:r0_15, ~mu0_2
685+
# 8| v0_17(Void) = UnmodeledUse : mu*
686+
# 8| v0_18(Void) = ExitFunction :
687+
688+
# 12| System.Void Indexers.Contact.set_Item(System.Int32,System.String)
689+
# 12| Block 0
690+
# 12| v0_0(Void) = EnterFunction :
691+
# 12| mu0_1(null) = AliasedDefinition :
692+
# 12| mu0_2(null) = UnmodeledDefinition :
693+
# 12| r0_3(glval<Contact>) = InitializeThis :
694+
# 6| r0_4(glval<Int32>) = VariableAddress[index] :
695+
# 6| mu0_5(Int32) = InitializeParameter[index] : &:r0_4
696+
# 12| r0_6(glval<String>) = VariableAddress[value] :
697+
# 12| mu0_7(String) = InitializeParameter[value] : &:r0_6
698+
# 14| r0_8(glval<String>) = VariableAddress[value] :
699+
# 14| r0_9(String) = Load : &:r0_8, ~mu0_2
700+
# 14| r0_10(Contact) = CopyValue : r0_3
701+
# 14| r0_11(glval<String[]>) = FieldAddress[address] : r0_10
702+
# 14| r0_12(String[]) = ElementsAddress : r0_11
703+
# 14| r0_13(glval<Int32>) = VariableAddress[index] :
704+
# 14| r0_14(Int32) = Load : &:r0_13, ~mu0_2
705+
# 14| r0_15(String[]) = PointerAdd[4] : r0_12, r0_14
706+
# 14| mu0_16(String) = Store : &:r0_15, r0_9
707+
# 12| v0_17(Void) = ReturnVoid :
708+
# 12| v0_18(Void) = UnmodeledUse : mu*
709+
# 12| v0_19(Void) = ExitFunction :
710+
711+
# 19| System.Void Indexers.Main()
712+
# 19| Block 0
713+
# 19| v0_0(Void) = EnterFunction :
714+
# 19| mu0_1(null) = AliasedDefinition :
715+
# 19| mu0_2(null) = UnmodeledDefinition :
716+
# 21| r0_3(glval<Contact>) = VariableAddress[contact] :
717+
# 21| r0_4(Contact) = NewObj :
718+
# 21| r0_5(glval<null>) = FunctionAddress[Contact] :
719+
# 21| v0_6(Void) = Call : func:r0_5, this:r0_4
720+
# 21| mu0_7(null) = ^CallSideEffect : ~mu0_2
721+
# 21| mu0_8(Contact) = Store : &:r0_3, r0_4
722+
# 22| r0_9(glval<Contact>) = VariableAddress[contact] :
723+
# 22| r0_10(Contact) = Load : &:r0_9, ~mu0_2
724+
# 22| r0_11(glval<null>) = FunctionAddress[set_Item] :
725+
# 22| r0_12(Int32) = Constant[0] :
726+
# 22| r0_13(String) = StringConstant["Begumpet"] :
727+
# 22| v0_14(Void) = Call : func:r0_11, this:r0_10, 0:r0_12, 1:r0_13
728+
# 22| mu0_15(null) = ^CallSideEffect : ~mu0_2
729+
# 23| r0_16(glval<Contact>) = VariableAddress[contact] :
730+
# 23| r0_17(Contact) = Load : &:r0_16, ~mu0_2
731+
# 23| r0_18(glval<null>) = FunctionAddress[set_Item] :
732+
# 23| r0_19(Int32) = Constant[1] :
733+
# 23| r0_20(String) = StringConstant["Hyderabad"] :
734+
# 23| v0_21(Void) = Call : func:r0_18, this:r0_17, 0:r0_19, 1:r0_20
735+
# 23| mu0_22(null) = ^CallSideEffect : ~mu0_2
736+
# 24| r0_23(glval<Contact>) = VariableAddress[contact] :
737+
# 24| r0_24(Contact) = Load : &:r0_23, ~mu0_2
738+
# 24| r0_25(glval<null>) = FunctionAddress[set_Item] :
739+
# 24| r0_26(Int32) = Constant[2] :
740+
# 24| r0_27(String) = StringConstant["Telengana"] :
741+
# 24| v0_28(Void) = Call : func:r0_25, this:r0_24, 0:r0_26, 1:r0_27
742+
# 24| mu0_29(null) = ^CallSideEffect : ~mu0_2
743+
# 19| v0_30(Void) = ReturnVoid :
744+
# 19| v0_31(Void) = UnmodeledUse : mu*
745+
# 19| v0_32(Void) = ExitFunction :
746+
601747
inheritance_polymorphism.cs:
602748
# 3| System.Int32 A.function()
603749
# 3| Block 0

0 commit comments

Comments
 (0)