Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ClientOfficialVersion>3.52.0</ClientOfficialVersion>
<ClientPreviewVersion>3.53.0</ClientPreviewVersion>
<ClientPreviewSuffixVersion>preview.0</ClientPreviewSuffixVersion>
<DirectVersion>3.39.1</DirectVersion>
<DirectVersion>3.40.1</DirectVersion>
<FaultInjectionVersion>1.0.0</FaultInjectionVersion>
<FaultInjectionSuffixVersion>beta.0</FaultInjectionSuffixVersion>
<EncryptionOfficialVersion>2.0.5</EncryptionOfficialVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,21 @@ public void Update(IDictionary<string, object> queryengineConfiguration)

if (!this.disposed && this.serviceProvider != IntPtr.Zero)
{
uint errorCode = ServiceInteropWrapper.UpdateServiceProvider(
this.serviceProvider,
this.queryengineConfiguration);
try
{
uint errorCode = ServiceInteropWrapper.UpdateServiceProvider(
this.serviceProvider,
this.queryengineConfiguration);

Exception exception = Marshal.GetExceptionForHR((int)errorCode);
if (exception != null) throw exception;
Exception exception = Marshal.GetExceptionForHR((int)errorCode);
if (exception != null) throw exception;
}
catch (AccessViolationException avEx)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't catch AccessViolationException anymore.

{
// Handle AccessViolationException specifically for UpdateServiceProvider
DefaultTrace.TraceWarning("QueryPartitionProvider.Update failed with AccessViolationException: {0}", avEx.Message);
throw new InvalidOperationException("Native service provider update failed due to memory access violation. This may indicate corrupted native libraries or incompatible configuration.", avEx);
}
}
}
}
Expand Down Expand Up @@ -378,6 +387,24 @@ internal static TryCatch<IntPtr> TryCreateServiceProvider(string queryEngineConf
{
try
{
// Add defensive checks for the configuration parameter
if (string.IsNullOrEmpty(queryEngineConfiguration))
{
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed: queryEngineConfiguration is null or empty");
return TryCatch<IntPtr>.FromException(new ArgumentException("queryEngineConfiguration cannot be null or empty"));
}

// Validate that the configuration is valid JSON
try
{
JsonConvert.DeserializeObject(queryEngineConfiguration);
}
catch (JsonException jsonEx)
{
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed: invalid JSON configuration - {0}", jsonEx.Message);
return TryCatch<IntPtr>.FromException(new ArgumentException($"Invalid JSON configuration: {jsonEx.Message}", jsonEx));
}

IntPtr serviceProvider = IntPtr.Zero;
uint errorCode = ServiceInteropWrapper.CreateServiceProvider(
queryEngineConfiguration,
Expand All @@ -391,6 +418,12 @@ internal static TryCatch<IntPtr> TryCreateServiceProvider(string queryEngineConf

return TryCatch<IntPtr>.FromResult(serviceProvider);
}
catch (AccessViolationException avEx)
{
// Specifically handle AccessViolationException which indicates native memory corruption
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed with AccessViolationException: {0}", avEx.Message);
return TryCatch<IntPtr>.FromException(new InvalidOperationException("Native service provider creation failed due to memory access violation. This may indicate corrupted native libraries or incompatible configuration.", avEx));
}
catch (Exception ex)
{
DefaultTrace.TraceWarning("QueryPartitionProvider.TryCreateServiceProvider failed with exception {0}", ex.Message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,55 @@ public void TestPartitionedQueryExecutionInfoDeserialization()
new JsonSerializerSettings { Formatting = Formatting.None });
}

Assert.AreEqual(expected, actual);
}
Assert.AreEqual(expected, actual);
}
}

[TestMethod]
public void TestTryCreateServiceProviderWithNullConfiguration()
{
TryCatch<IntPtr> result = QueryPartitionProvider.TryCreateServiceProvider(null);

Assert.IsTrue(result.Failed);
Assert.IsInstanceOfType(result.Exception, typeof(ArgumentException));
Assert.IsTrue(result.Exception.Message.Contains("queryEngineConfiguration cannot be null or empty"));
}

[TestMethod]
public void TestTryCreateServiceProviderWithEmptyConfiguration()
{
TryCatch<IntPtr> result = QueryPartitionProvider.TryCreateServiceProvider(string.Empty);

Assert.IsTrue(result.Failed);
Assert.IsInstanceOfType(result.Exception, typeof(ArgumentException));
Assert.IsTrue(result.Exception.Message.Contains("queryEngineConfiguration cannot be null or empty"));
}

[TestMethod]
public void TestTryCreateServiceProviderWithInvalidJsonConfiguration()
{
string invalidJson = "{ invalid json }";
TryCatch<IntPtr> result = QueryPartitionProvider.TryCreateServiceProvider(invalidJson);

Assert.IsTrue(result.Failed);
Assert.IsInstanceOfType(result.Exception, typeof(ArgumentException));
Assert.IsTrue(result.Exception.Message.Contains("Invalid JSON configuration"));
}

[TestMethod]
public void TestTryCreateServiceProviderWithValidConfiguration()
{
IDictionary<string, object> configuration = new Dictionary<string, object>() { { "maxSqlQueryInputLength", 524288 } };
string jsonConfiguration = JsonConvert.SerializeObject(configuration);

// This will likely fail due to native dependencies not being available in test environment,
// but it should not throw an AccessViolationException
TryCatch<IntPtr> result = QueryPartitionProvider.TryCreateServiceProvider(jsonConfiguration);

// We expect this to fail in test environment, but gracefully
Assert.IsTrue(result.Failed);
// Should not be an ArgumentException since the JSON is valid
Assert.IsNotInstanceOfType(result.Exception, typeof(ArgumentException));
}
}
}
Loading