Skip to content
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

EncodedStringText.Decode does not handle memory stream with non-zero offset correctly #12348

Closed
nguerrera opened this issue Jul 5, 2016 · 4 comments
Assignees
Milestone

Comments

@nguerrera
Copy link
Contributor

nguerrera commented Jul 5, 2016

Version Used: 2.0 (Synced to master recently)

There's an optimization for memory stream in EncodedStringText.Decode, which retrieves the backing byte array if it can. This optimization does not account for a MemoryStream that was constructed with a non-zero offset. The fix should use MemoryStream.TryGetBuffer instead of MemoryStream.GetBuffer in order to get an array segment with the appropriate offset.

Steps to Reproduce:
Compile and run the following program.

(I'm not sure if the root issue in EncodedStringText.Decode can affect anything other than scripting. This was the first code path I found where the user could pass an arbitrary stream.)

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

class Resolver : SourceReferenceResolver
{
    public override bool Equals(object other) => ReferenceEquals(this, other);
    public override int GetHashCode() => 42;
    public override string ResolveReference(string path, string baseFilePath) => path;
    public override string NormalizePath(string path, string baseFilePath) => path;

    public override Stream OpenRead(string resolvedPath)
    {
        // Make an ASCII text buffer with Hello World script preceded by padding Qs
        const int padding = 42;
        string text = @"System.Console.WriteLine(""Hello World!"");";
        byte[] bytes = Enumerable.Repeat((byte)'Q', text.Length + padding).ToArray();
        Encoding.ASCII.GetBytes(text, 0, text.Length, bytes, padding);

        // Make a stream over the program portion, skipping the Qs.
        var stream = new MemoryStream(
            bytes,
            padding,
            text.Length,
            writable: false,
            publiclyVisible: true);

        // sanity check that reading entire stream gives us back our text.
        using (var streamReader = new StreamReader(
            stream,
            Encoding.ASCII,
            detectEncodingFromByteOrderMarks: false,
            bufferSize: bytes.Length,
            leaveOpen: true))
        {
            var textFromStream = streamReader.ReadToEnd();
            Debug.Assert(textFromStream == text);
        }

        stream.Position = 0;
        return stream;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var options = ScriptOptions.Default.WithSourceResolver(new Resolver());
        var script = CSharpScript.Create(@"#load ""foo.cs""", options);
        var result = script.RunAsync().Result;
    }
}

Expected Behavior:
Script runs and prints hello world.

Actual Behavior:
Unhandled Exception: Microsoft.CodeAnalysis.Scripting.CompilationErrorException: foo.cs(1,1): error CS0103: The name 'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ' does not exist in the current context

@nguerrera
Copy link
Contributor Author

nguerrera commented Aug 10, 2016

#12353 includes a fix for this.

@svick
Copy link
Contributor

svick commented Aug 10, 2016

@nguerrera It does? I don't see anything similar to #12408 in #12353 and running the above code when referencing code from #12353 still throws the exception for me.

@nguerrera
Copy link
Contributor Author

@svick You're right. Sorry, I commented on the wrong bug. Thanks for pointing it out.

@TyOverby
Copy link
Contributor

This bug was fixed in 418868bc

I can confirm that your program compiles and runs correctly now.

I'll add a regression test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants