Maximum amount of errors in CSharpCodeProvider.CompileAssemblyFromFile
Asked Answered
S

1

11

I use CSharpCodeProvider to compile instant plugins for my app.

Right now it is possible to try to compile a file, that looks good, but generates many errors, for example a C# code glued with a binary file. There are many characters, that are treated with error CS1056: Unexpected character.

This behaviour is expected, but a compilation process of such a "malicious" file is very time consuming.

One solution that I find reasonable would be to limit the number of errors, after which CSharpCodeProvider.CompileAssemblyFromFile returns.

Is it possible to set such a limit?

I don't really want to inspect the file very carefully in the first place, if it's possible to avoid.

Suggs answered 14/6, 2013 at 13:3 Comment(8)
if there is even a remote risk that the incoming file is malicious, personally I wouldn't be trusting it enough even to let it near a compiler; there are some interesting cases (Eric Lippert would have a list, no doubt) of things in valid-looking C# that are disproportionately expensive for the compiler to try to figure outSaleratus
@MarcGravell: In particular, nasty combinations of overload resolution with type inference (see Eric Lippert's blog post about 3SAT). However, setting a hard timeout on the compilation process should make it safe.Inn
@MarcGravell - you have a valid point, but, well, I do want to be able to load a file and try. I know it can be dangerous etc., but, well, that really is what I want.Suggs
@Inn yeah, I was thinking of a particular blog entry of his where it is expanding generics based on constraints, and each iteration the compiler's problem actually becomes bigger, until the compiler actually stack-overflows - at which point it logs a compiler message about being too complex; but I can't find itSaleratus
@Inn - I could make a Task and kill it after a time, but I'd love to receive the list of errors from CSharpCodeProvider. I'd only want to have only a limited number of them :)Suggs
@PiotrZierhoffer to the best of my knowledge, no that doesn't exist currently. You might want to check whether the new managed compiler (preview) supports this.Saleratus
I wonder if upcoming roslyn relase blogs.msdn.com/b/csharpfaq/archive/2013/12/16/… will allow compiling an untusted code in the way that it will protect an application that runs it from unforeseen issuesHabilitate
@Habilitate Well, it would be nice to have a nice API and a common-sense level of security for that, but, as Mark Gravell said, I don't really know if it would be a considered scenario. Let us hope :)Suggs
H
1

I don't know if there's a property or field of CSharpCodeProvider that can control this, but a possible solution is to change the question you're asking- if the problem is the time it takes to attempt compilation, rather than the number of errors, my solution would be to run the CSharpCodeProvider on a separate task, but kill the task if it takes too long to complete.

Then you can provide your own error message:

"Your code is too bad. It can't be compiled in less than 5 minutes." :P

As for security, you might try running things in a separate AppDomain via Application.Run? Dunno how complex your application is, but you might start a new instance of your main form with the plugin injected.

Hyetology answered 10/2, 2014 at 4:18 Comment(4)
Makes sense, but does not really resolve my issue. I'd love to have an information on the errors encountered so far (at least the first one)Suggs
As far as I can tell, the only way to get errors of a compilation done by a CSharpCodeProvider instance is the Errors property of the CompilerResults that's returned AFTER it compiles everything. One way I can think to check that value DURING compilation is by using reflection to get the underlying field of that Errors property (assuming you can track down the CompilerResults object, which is likely constructed when CompileAssemblyFrom* is called). Assumably, that field will be a type of collection, so you can end the task if it's added to, and get what's added to it to display in your errors.Hyetology
That would be very slow, reflecting code that's being executed, and it might not even be possible on separate threads. It's also very hackish. Please update this question if you do find a better answer- I'm very curious now that I've done all this research to try and answer ;)Hyetology
That is an interesting idea, but will definitely lead to problems. I'd need to pause the compiler thread and analyse it's stacktrace, or even the stack itself. It's certainly an evil way to go :) On the other hand, it's most probably impossible, due to expected P/Invokes inside. So that's exactly my problem - I want to limit the number of errors in CompilerResults.Errors, so I don't have to hack the entire .net machine :) Still waiting for Roslyn then.Suggs

© 2022 - 2024 — McMap. All rights reserved.