-
Notifications
You must be signed in to change notification settings - Fork 1.9k
C#: Reduce size of getAThrownException()
#990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C#: Reduce size of getAThrownException()
#990
Conversation
In the precense of multiple core libraries, `getAThrownException()` would return multiple copies of the same exception, say `System.OverflowException`, one for each core library. With this change we try to identify which core library a given control flow element was compiled against, and only return the corresponding version.
| * core type inside assembly `a`. | ||
| */ | ||
| pragma[noinline] | ||
| private predicate assemblyCompiledWithCoreLib(Assembly a, Assembly core) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calumgrant : Can you think of a better way to do this?
|
Performance unchanged by this change (internal link): https://git.semmle.com/gist/tom/09129553dee65e843c2376651987ce33. |
|
I have 2 other ideas, which may well prove to be worse than this, but I thought I would put them here.
|
This would require an extractor change, and it seems to me a bit ad hoc to treat exception types specially.
That might work, but would you prefer that for better performance of higher precision? |
Not necessarily. You could use QL to create something like
It might be a little simpler and faster. Don't know. |
Makes sense. My only concern is that we would then also have to canonicalize explicitly thrown exceptions, |
Yes, I wonder if it could be the case that a library throws |
|
But possibly, |
When determining which core library a "tried control flow element" is compiled against, first look at exceptions caught by the surrounding `try` block, then look at assembly attributes, and finally choose (randomly) the core library with the highest lexicographic order.
calumgrant
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approach LGTM. I guess this is quite hard to qltest, but I'd be interested in seeing the effect on performance.
| private Assembly getCoreLib() { assemblyCompiledWithCoreLib(this.getAssembly(), result) } | ||
| private CoreLib getCoreLibFromACatchClause() { | ||
| exists(SpecificCatchClause scc | scc = try.getACatchClause() | | ||
| result = scc.getCaughtExceptionType().getABaseType*().getALocation() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that might go a bit wrong here is that you'll end up querying ObjectType.getALocation() which will in fact return all CoreLibs. So perhaps
result = scc.getCaughtExceptionType().getBaseClass*().(SystemExceptionClass).getALocation()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also getBaseClass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a clear oversight, good spot!
| strictcount(stm.getSystemAssembly()) = 1 | ||
| ) | ||
| private predicate assemblyCompiledWithCoreLib(Assembly a, CoreLib core) { | ||
| a.getAnAttribute().getType().getABaseType*().getALocation() = core |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core = a.getAnAttribute().getType().getBaseClass*().(SystemAttributeClass).getALocation()
otherwise we'll end up getting the location of ObjectType which will be all of them.
Also note getBaseClass() as we don't care about interfaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just remembered that only source assemblies have attributes (due to extractor limitations). I don't think this affects anything here but is worth bearing in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, good spot :-)
In the precense of multiple core libraries,
getAThrownException()would returnmultiple copies of the same exception, say
System.OverflowException, one for eachcore library. With this change we try to identify which core library a given control
flow element was compiled against, and only return the corresponding version.