From adb9da0c0cc39305b191e5bbe50a783645f95e07 Mon Sep 17 00:00:00 2001 From: Anand Krishnamoorthi <35780660+anakrish@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:58:51 -0700 Subject: [PATCH] fix: Null terminate C# strings in Rust boundary (#318) Signed-off-by: Anand Krishnamoorthi --- bindings/csharp/net40/Regorus.cs | 368 +++++++++++++++--------------- bindings/csharp/net8.0/Regorus.cs | 358 +++++++++++++++-------------- 2 files changed, 372 insertions(+), 354 deletions(-) diff --git a/bindings/csharp/net40/Regorus.cs b/bindings/csharp/net40/Regorus.cs index 42a6cd47..041126de 100644 --- a/bindings/csharp/net40/Regorus.cs +++ b/bindings/csharp/net40/Regorus.cs @@ -19,185 +19,195 @@ namespace Microsoft.WindowsAzure.Regorus.IaaS { - public class RegorusPolicyEngine : ICloneable, IDisposable - { - unsafe private RegorusFFI.RegorusEngine* E; - - public RegorusPolicyEngine() - { - unsafe - { - E = RegorusFFI.API.regorus_engine_new(); - } - } - - - public void Dispose() - { - unsafe - { - if (E != null) - { - RegorusFFI.API.regorus_engine_drop(E); - // to avoid Dispose() being called multiple times by mistake. - E = null; - } - - } - - } - - public object Clone() - { - var clone = (RegorusPolicyEngine)this.MemberwiseClone(); - unsafe - { - clone.E = RegorusFFI.API.regorus_engine_clone(E); - } - return clone; - - } - - public void AddPolicy(string path, string rego) - { - var pathBytes = Encoding.UTF8.GetBytes(path); - var regoBytes = Encoding.UTF8.GetBytes(rego); - - unsafe - { - fixed (byte* pathPtr = pathBytes) - { - fixed(byte* regoPtr = regoBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr)); - } - } - } - } - - public void AddPolicyFromFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); - - unsafe - { - fixed (byte* pathPtr = pathBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr)); - } - } - } - - public void AddPolicyFromPath(string path) - { - if (!Directory.Exists(path)) - { - return; - } - - string[] regoFiles = Directory.GetFiles(path, "*.rego", SearchOption.AllDirectories); - foreach (string file in regoFiles) - { - AddPolicyFromFile(file); - } - } - - public void AddDataJson(string data) - { - var dataBytes = Encoding.UTF8.GetBytes(data); - - unsafe - { - fixed (byte* dataPtr = dataBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr)); - - } - } - } - - public void AddDataFromJsonFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); - - unsafe - { - fixed (byte* pathPtr = pathBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr)); - - } - } - } - - public void SetInputJson(string input) - { - var inputBytes = Encoding.UTF8.GetBytes(input); - - unsafe - { - fixed (byte* inputPtr = inputBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr)); - - } - } - } - - public void SetInputFromJsonFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); - - unsafe - { - fixed (byte* pathPtr = pathBytes) - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr)); - - } - } - } - - public string EvalQuery(string query) - { - var queryBytes = Encoding.UTF8.GetBytes(query); - - var resultJson = ""; - unsafe - { - fixed (byte* queryPtr = queryBytes) - { - var result = RegorusFFI.API.regorus_engine_eval_query(E, queryPtr); - if (result.status == RegorusFFI.RegorusStatus.RegorusStatusOk) { - if (result.output != null) { - resultJson = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.output); - } - RegorusFFI.API.regorus_result_drop(result); - } else { - CheckAndDropResult(result); - } - - } - } - if (resultJson != null) { - return resultJson; - } else { - return ""; - } - } - - void CheckAndDropResult(RegorusFFI.RegorusResult result) - { - if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) { - unsafe { - var message = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.error_message); - var ex = new Exception(message); - RegorusFFI.API.regorus_result_drop(result); - throw ex; - } - } - RegorusFFI.API.regorus_result_drop(result); - } + public class RegorusPolicyEngine : ICloneable, IDisposable + { + unsafe private RegorusFFI.RegorusEngine* E; + + public RegorusPolicyEngine() + { + unsafe + { + E = RegorusFFI.API.regorus_engine_new(); + } + } + + + public void Dispose() + { + unsafe + { + if (E != null) + { + RegorusFFI.API.regorus_engine_drop(E); + // to avoid Dispose() being called multiple times by mistake. + E = null; + } + + } + + } + + public object Clone() + { + var clone = (RegorusPolicyEngine)this.MemberwiseClone(); + unsafe + { + clone.E = RegorusFFI.API.regorus_engine_clone(E); + } + return clone; + + } + + byte[] NullTerminatedUTF8Bytes(string s) + { + return Encoding.UTF8.GetBytes(s + char.MinValue); + } + + public void AddPolicy(string path, string rego) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + var regoBytes = NullTerminatedUTF8Bytes(rego); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + fixed (byte* regoPtr = regoBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr)); + } + } + } + } + + public void AddPolicyFromFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr)); + } + } + } + + public void AddPolicyFromPath(string path) + { + if (!Directory.Exists(path)) + { + return; + } + + string[] regoFiles = Directory.GetFiles(path, "*.rego", SearchOption.AllDirectories); + foreach (string file in regoFiles) + { + AddPolicyFromFile(file); + } + } + + public void AddDataJson(string data) + { + var dataBytes = NullTerminatedUTF8Bytes(data); + + unsafe + { + fixed (byte* dataPtr = dataBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr)); + } + } + } + + public void AddDataFromJsonFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr)); + + } + } + } + + public void SetInputJson(string input) + { + var inputBytes = NullTerminatedUTF8Bytes(input); + + unsafe + { + fixed (byte* inputPtr = inputBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr)); + } + } + } + + public void SetInputFromJsonFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr)); + } + } + } + + public string EvalQuery(string query) + { + var queryBytes = NullTerminatedUTF8Bytes(query); + + var resultJson = ""; + unsafe + { + fixed (byte* queryPtr = queryBytes) + { + var result = RegorusFFI.API.regorus_engine_eval_query(E, queryPtr); + if (result.status == RegorusFFI.RegorusStatus.RegorusStatusOk) + { + if (result.output != null) + { + resultJson = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.output); + } + RegorusFFI.API.regorus_result_drop(result); + } + else + { + CheckAndDropResult(result); + } + } + } + if (resultJson != null) + { + return resultJson; + } + else + { + return ""; + } + } + + void CheckAndDropResult(RegorusFFI.RegorusResult result) + { + if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) + { + unsafe + { + var message = System.Runtime.InteropServices.Marshal.PtrToStringAnsi((IntPtr)result.error_message); + var ex = new Exception(message); + RegorusFFI.API.regorus_result_drop(result); + throw ex; + } + } + RegorusFFI.API.regorus_result_drop(result); + } } } diff --git a/bindings/csharp/net8.0/Regorus.cs b/bindings/csharp/net8.0/Regorus.cs index fac09ee0..72ce2c2f 100644 --- a/bindings/csharp/net8.0/Regorus.cs +++ b/bindings/csharp/net8.0/Regorus.cs @@ -2,219 +2,227 @@ namespace Regorus { - public class Exception : System.Exception - { - public Exception(string? message) : base(message) {} - } - - public class Engine : ICloneable - { - unsafe private RegorusFFI.RegorusEngine* E; - public Engine() + public class Exception : System.Exception { - unsafe - { - E = RegorusFFI.API.regorus_engine_new(); - } + public Exception(string? message) : base(message) { } } - public object Clone() + public class Engine : ICloneable { - var clone = (Engine)this.MemberwiseClone(); - unsafe - { - clone.E = RegorusFFI.API.regorus_engine_clone(E); - } - return clone; + unsafe private RegorusFFI.RegorusEngine* E; + public Engine() + { + unsafe + { + E = RegorusFFI.API.regorus_engine_new(); + } + } - } + public object Clone() + { + var clone = (Engine)this.MemberwiseClone(); + unsafe + { + clone.E = RegorusFFI.API.regorus_engine_clone(E); + } + return clone; - public string AddPolicy(string path, string rego) - { - var pathBytes = Encoding.UTF8.GetBytes(path); - var regoBytes = Encoding.UTF8.GetBytes(rego); + } + + byte[] NullTerminatedUTF8Bytes(string s) + { + return Encoding.UTF8.GetBytes(s + char.MinValue); + } - unsafe - { - fixed (byte* pathPtr = pathBytes) + public string AddPolicy(string path, string rego) { - fixed(byte* regoPtr = regoBytes) - { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr)); - } + var pathBytes = NullTerminatedUTF8Bytes(path); + var regoBytes = NullTerminatedUTF8Bytes(rego); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + fixed (byte* regoPtr = regoBytes) + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy(E, pathPtr, regoPtr)); + } + } + } } - } - } - public string AddPolicyFromFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); + public string AddPolicyFromFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr)); + } + } + } - unsafe - { - fixed (byte* pathPtr = pathBytes) + public void AddDataJson(string data) { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_add_policy_from_file(E, pathPtr)); + var dataBytes = NullTerminatedUTF8Bytes(data); + + unsafe + { + fixed (byte* dataPtr = dataBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr)); + } + } } - } - } - public void AddDataJson(string data) - { - var dataBytes = Encoding.UTF8.GetBytes(data); + public void AddDataFromJsonFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr)); + } + } + } - unsafe - { - fixed (byte* dataPtr = dataBytes) + public void SetInputJson(string input) { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_json(E, dataPtr)); + var inputBytes = NullTerminatedUTF8Bytes(input); + + unsafe + { + fixed (byte* inputPtr = inputBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr)); + } + } } - } - } - public void AddDataFromJsonFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); + public void SetInputFromJsonFile(string path) + { + var pathBytes = NullTerminatedUTF8Bytes(path); + + unsafe + { + fixed (byte* pathPtr = pathBytes) + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr)); + } + } + } - unsafe - { - fixed (byte* pathPtr = pathBytes) + public string EvalQuery(string query) { - CheckAndDropResult(RegorusFFI.API.regorus_engine_add_data_from_json_file(E, pathPtr)); + var queryBytes = NullTerminatedUTF8Bytes(query); + + unsafe + { + fixed (byte* queryPtr = queryBytes) + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, queryPtr)); + } + } } - } - } - public void SetInputJson(string input) - { - var inputBytes = Encoding.UTF8.GetBytes(input); + public string EvalRule(string rule) + { + var ruleBytes = NullTerminatedUTF8Bytes(rule); + + unsafe + { + fixed (byte* rulePtr = ruleBytes) + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, rulePtr)); + } + } + } - unsafe - { - fixed (byte* inputPtr = inputBytes) + public void SetEnableCoverage(bool enable) { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_json(E, inputPtr)); + unsafe + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_enable_coverage(E, enable)); + } } - } - } - public void SetInputFromJsonFile(string path) - { - var pathBytes = Encoding.UTF8.GetBytes(path); + public void ClearCoverageData() + { + unsafe + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_clear_coverage_data(E)); + } + } - unsafe - { - fixed (byte* pathPtr = pathBytes) + public string GetCoverageReport() { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_input_from_json_file(E, pathPtr)); + unsafe + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report(E)); + } } - } - } - public string EvalQuery(string query) - { - var queryBytes = Encoding.UTF8.GetBytes(query); + public string GetCoverageReportPretty() + { + unsafe + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report_pretty(E)); + } + } - unsafe - { - fixed (byte* queryPtr = queryBytes) + public void SetGatherPrints(bool enable) { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, queryPtr)); + unsafe + { + CheckAndDropResult(RegorusFFI.API.regorus_engine_set_gather_prints(E, enable)); + } } - } - } - public string EvalRule(string rule) - { - var ruleBytes = Encoding.UTF8.GetBytes(rule); + public string TakePrints() + { + unsafe + { + return CheckAndDropResult(RegorusFFI.API.regorus_engine_take_prints(E)); + } + } - unsafe - { - fixed (byte* rulePtr = ruleBytes) + ~Engine() { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_eval_query(E, rulePtr)); + unsafe + { + RegorusFFI.API.regorus_engine_drop(E); + } } - } - } - - public void SetEnableCoverage(bool enable) - { - unsafe - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_enable_coverage(E, enable)); - } - } - - public void ClearCoverageData() - { - unsafe - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_clear_coverage_data(E)); - } - } - - public string GetCoverageReport() - { - unsafe - { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report(E)); - } - } - - public string GetCoverageReportPretty() - { - unsafe - { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_get_coverage_report_pretty(E)); - } - } - - public void SetGatherPrints(bool enable) - { - unsafe - { - CheckAndDropResult(RegorusFFI.API.regorus_engine_set_gather_prints(E, enable)); - } - } - - public string TakePrints() - { - unsafe - { - return CheckAndDropResult(RegorusFFI.API.regorus_engine_take_prints(E)); - } - } - - ~Engine() - { - unsafe - { - RegorusFFI.API.regorus_engine_drop(E); - } - } - string CheckAndDropResult(RegorusFFI.RegorusResult result) - { - if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) { - unsafe { - var message = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.error_message); - var ex = new Exception(message); - RegorusFFI.API.regorus_result_drop(result); - throw ex; - } - } - - var resultString = ""; - unsafe - { - if (result.output is not null) { - resultString = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.output); - } - RegorusFFI.API.regorus_result_drop(result); - } - return resultString; - } + string CheckAndDropResult(RegorusFFI.RegorusResult result) + { + if (result.status != RegorusFFI.RegorusStatus.RegorusStatusOk) + { + unsafe + { + var message = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.error_message); + var ex = new Exception(message); + RegorusFFI.API.regorus_result_drop(result); + throw ex; + } + } + + var resultString = ""; + unsafe + { + if (result.output is not null) + { + resultString = System.Runtime.InteropServices.Marshal.PtrToStringUTF8((IntPtr)result.output); + } + RegorusFFI.API.regorus_result_drop(result); + } + return resultString; + } - } + } }