mirror of
https://github.com/microsoft/regorus.git
synced 2026-08-05 02:16:11 +00:00
* fix(ffi): eliminate aliasing UB via to_shared_ref migration Add to_shared_ref() helper that creates &T (shared reference) from raw pointers instead of &mut T. This eliminates undefined behavior caused by violating Rust's aliasing invariant when C# SafeHandle permits concurrent FFI calls on the same handle. With &mut T, the compiler may assume exclusive (noalias) access and reorder or elide reads/writes — a miscompilation risk when another thread holds a reference to the same object. Switching to &T removes that assumption; actual mutation is mediated by the interior RwLock inside Handle<T>, which is the sole synchronization mechanism. Migrated sites: - rvm.rs: 20 non-drop call sites - engine.rs: 30 non-drop call sites + with_unwind_guard for timer fns - compiled_policy.rs: 2 call sites - Fix null-data UB in regorus_program_deserialize_binary Drop paths retain to_ref() where exclusive access is guaranteed by the caller contract (preventing use-after-free). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(ffi): add Azure Policy JSON compilation FFI and C# bindings - AliasRegistry builder pattern: RegorusAliasRegistryBuilder (mutable, single-threaded) + RegorusAliasRegistry (immutable, Arc-wrapped) - Azure Policy JSON compilation: regorus_compile_azure_policy_rule and regorus_compile_azure_policy_definition with alias registry support - regorus_rvm_set_context for host-supplied ambient data - C# AliasRegistryBuilder and AliasRegistry classes with convenience factories (FromJson, FromManifest, Empty) - C# AzurePolicyCompiler static class for policy rule/definition compilation - Compile functions take *const RegorusAliasRegistry (read-only via to_shared_ref for concurrent compilation safety) - Fix pre-existing clippy warnings across multiple crates Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
129 lines
4.7 KiB
C#
129 lines
4.7 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System;
|
|
using Regorus.Internal;
|
|
|
|
#nullable enable
|
|
namespace Regorus
|
|
{
|
|
/// <summary>
|
|
/// Immutable Azure Policy alias registry used for resource normalization
|
|
/// and policy compilation.
|
|
/// </summary>
|
|
public unsafe sealed class AliasRegistry : SafeHandleWrapper
|
|
{
|
|
internal AliasRegistry(RegorusAliasRegistryHandle handle)
|
|
: base(handle, nameof(AliasRegistry))
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create an empty immutable alias registry.
|
|
/// </summary>
|
|
public static AliasRegistry Empty()
|
|
{
|
|
using var builder = new AliasRegistryBuilder();
|
|
return builder.Build();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create an immutable alias registry from control-plane alias JSON.
|
|
/// </summary>
|
|
public static AliasRegistry FromJson(string json)
|
|
{
|
|
using var builder = new AliasRegistryBuilder();
|
|
builder.LoadJson(json);
|
|
return builder.Build();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create an immutable alias registry from a data-plane manifest JSON document.
|
|
/// </summary>
|
|
public static AliasRegistry FromManifest(string json)
|
|
{
|
|
using var builder = new AliasRegistryBuilder();
|
|
builder.LoadManifest(json);
|
|
return builder.Build();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the number of resource types loaded in the registry.
|
|
/// </summary>
|
|
public long Length
|
|
{
|
|
get
|
|
{
|
|
return UseHandle(regPtr =>
|
|
{
|
|
return ResultHelpers.GetIntResult(
|
|
API.regorus_alias_registry_len((RegorusAliasRegistry*)regPtr));
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Normalize an ARM resource JSON and wrap it into the standard input envelope
|
|
/// expected by a compiled Azure Policy program.
|
|
/// </summary>
|
|
public string? NormalizeAndWrap(string resourceJson, string? apiVersion = null, string contextJson = "{}", string parametersJson = "{}")
|
|
{
|
|
return Utf8Marshaller.WithUtf8(resourceJson, resPtr =>
|
|
Utf8Marshaller.WithUtf8(contextJson, ctxPtr =>
|
|
Utf8Marshaller.WithUtf8(parametersJson, paramsPtr =>
|
|
{
|
|
if (apiVersion is null)
|
|
{
|
|
return UseHandle(regPtr =>
|
|
{
|
|
return ResultHelpers.GetStringResult(
|
|
API.regorus_alias_registry_normalize_and_wrap(
|
|
(RegorusAliasRegistry*)regPtr,
|
|
(byte*)resPtr, null,
|
|
(byte*)ctxPtr, (byte*)paramsPtr));
|
|
});
|
|
}
|
|
|
|
return Utf8Marshaller.WithUtf8(apiVersion, apiPtr =>
|
|
UseHandle(regPtr =>
|
|
{
|
|
return ResultHelpers.GetStringResult(
|
|
API.regorus_alias_registry_normalize_and_wrap(
|
|
(RegorusAliasRegistry*)regPtr,
|
|
(byte*)resPtr, (byte*)apiPtr,
|
|
(byte*)ctxPtr, (byte*)paramsPtr));
|
|
}));
|
|
})));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Denormalize a previously-normalized resource JSON back to ARM format.
|
|
/// </summary>
|
|
public string? Denormalize(string normalizedJson, string? apiVersion = null)
|
|
{
|
|
return Utf8Marshaller.WithUtf8(normalizedJson, normPtr =>
|
|
{
|
|
if (apiVersion is null)
|
|
{
|
|
return UseHandle(regPtr =>
|
|
{
|
|
return ResultHelpers.GetStringResult(
|
|
API.regorus_alias_registry_denormalize(
|
|
(RegorusAliasRegistry*)regPtr,
|
|
(byte*)normPtr, null));
|
|
});
|
|
}
|
|
|
|
return Utf8Marshaller.WithUtf8(apiVersion, apiPtr =>
|
|
UseHandle(regPtr =>
|
|
{
|
|
return ResultHelpers.GetStringResult(
|
|
API.regorus_alias_registry_denormalize(
|
|
(RegorusAliasRegistry*)regPtr,
|
|
(byte*)normPtr, (byte*)apiPtr));
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
}
|