System.AccessViolationException when opening Stream on query results that also contain a literal
The following throws when attempting to read a stream from a substring of a column value when the query also selects a literal value. The type of the literal value doesn't seem to matter - could be an integer, could be a string.
Either of the following adjustments to the query below allow this to work:
- Remove
42from the SELECT - Remove the
substring, selectingContentdirectly.
Repro:
<PackageReference Include="Microsoft.Data.Sqlite" Version="6.0.2" />
SQLitePCLRaw.bundle_e_sqlite3 2.0.6
using Microsoft.Data.Sqlite;
using var conn = new SqliteConnection("Data Source=:memory:");
conn.Open();
using var cmd = conn.CreateCommand();
cmd.CommandText = @"CREATE TABLE ""Case"" (""Name"" TEXT, ""Content"" BLOB)";
cmd.ExecuteNonQuery();
cmd.CommandText = @"INSERT INTO ""Case"" (Content) VALUES (x'23464f4f23')";
cmd.ExecuteNonQuery();
cmd.CommandText = @"SELECT substr(Content, 2, 3), 42 FROM ""Case"" ";
using var reader = cmd.ExecuteReader();
reader.Read();
// This part works, outputting "FOO" and 42 as expected.
Console.WriteLine(reader.GetString(0));
Console.WriteLine(reader.GetInt32(1));
// This throws:
using var stream = reader.GetStream(0);
var ms = new MemoryStream();
await stream.CopyToAsync(ms);
var content = ms.ToArray();
// Expected output: FOO
Console.WriteLine(System.Text.Encoding.ASCII.GetString(content));
Exception
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
at SQLitePCL.SQLite3Provider_e_sqlite3+NativeMethods.sqlite3_table_column_metadata(SQLitePCL.sqlite3, Byte*, Byte*, Byte*, Byte* ByRef, Byte* ByRef, Int32 ByRef, Int32 ByRef, Int32 ByRef)
--------------------------------
at SQLitePCL.SQLite3Provider_e_sqlite3.SQLitePCL.ISQLite3Provider.sqlite3_table_column_metadata(SQLitePCL.sqlite3, SQLitePCL.utf8z, SQLitePCL.utf8z, SQLitePCL.utf8z, SQLitePCL.utf8z ByRef, SQLitePCL.utf8z ByRef, Int32 ByRef, Int32 ByRef, Int32 ByRef)
at SQLitePCL.raw.sqlite3_table_column_metadata(SQLitePCL.sqlite3, SQLitePCL.utf8z, SQLitePCL.utf8z, SQLitePCL.utf8z, SQLitePCL.utf8z ByRef, SQLitePCL.utf8z ByRef, Int32 ByRef, Int32 ByRef, Int32 ByRef)
at SQLitePCL.raw.sqlite3_table_column_metadata(SQLitePCL.sqlite3, System.String, System.String, System.String, System.String ByRef, System.String ByRef, Int32 ByRef, Int32 ByRef, Int32 ByRef)
at Microsoft.Data.Sqlite.SqliteDataRecord.GetStream(Int32)
at Microsoft.Data.Sqlite.SqliteDataReader.GetStream(Int32)
at Program+<<Main>$>d__0.MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
at Program.<Main>$(System.String[])
at Program.<Main>(System.String[])
I've just looked a bit at the stack trace and at the code for SqliteDataRecord.GetStream(Int32) in Microsoft.Data.Sqlite.
It's possible that I've got a bug in sqlite3_table_column_metadata. If so, it should be possible to construct a repro that doesn't involve Microsoft.Data.Sqlite.
The other possibility is that Microsoft.Data.Sqlite has a problem in the way it is calling these functions. Not sure.
Cc @bricelam
Feel free to file an issue on dotnet/efcore if you'd like us to do the initial investigation.