/* ======================================================================== * Copyright (c) 2005-2026 The OPC Foundation, Inc. All rights reserved. * OPC Foundation MIT License 1.00. See LICENSE.txt in the repository root. * ======================================================================*/ using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using System.Text.Json.Nodes; using System.Threading; namespace Opc.Ua.OneFuzz.TestTarget { /// /// Synthetic callbacks for subprocess contract tests. NEVER publish or register /// this assembly as a service target: NegativeControl deliberately crashes, /// exits without a receipt, or spins forever on its reserved control inputs. /// public static class ContractCallbacks { /// /// Provides an observable independent of the validator's own receipts. /// public static void Inspect(ReadOnlySpan input) { Console.WriteLine($"contract-executed:Inspect:{FixtureDependency.Hash(input)}"); } /// /// A second exact callback with a different seed inventory. /// public static void Measure(ReadOnlySpan input) { Console.WriteLine($"contract-executed:Measure:{FixtureDependency.Hash(input)}"); } /// /// Explicit NEGATIVE CONTROL, never a service target. Ordinary fixture seeds /// return normally; only the reserved inputs below activate destructive behavior. /// public static void NegativeControl(ReadOnlySpan input) { ReadOnlySpan receiptPrefix = "onefuzz-contract:receipt-"u8; if (input.StartsWith(receiptPrefix)) { string change = Encoding.UTF8.GetString(input[receiptPrefix.Length..]); WriteControlMarker("receipt-" + change); WriteIncorrectReceipt(change, input); Environment.Exit(0); } if (input.SequenceEqual("onefuzz-contract:throw"u8)) { WriteControlMarker("throw"); throw new InvalidOperationException("SYNTHETIC_ONEFUZZ_CALLBACK_EXCEPTION"); } if (input.SequenceEqual("onefuzz-contract:exit0"u8)) { WriteControlMarker("exit0"); Environment.Exit(0); } if (input.SequenceEqual("onefuzz-contract:spin"u8)) { WriteControlMarker("spin"); // Intentionally synchronous and noncooperative: only a process kill // can terminate this negative control. No timers or cancellation token. while (true) { Interlocked.Increment(ref s_spinIterations); } } Console.WriteLine($"contract-executed:NegativeControl:{FixtureDependency.Hash(input)}"); } private static void WriteControlMarker(string control) { using Process process = Process.GetCurrentProcess(); Console.WriteLine(string.Create( CultureInfo.InvariantCulture, $"negative-control:{control}:{process.Id}:{process.StartTime.ToUniversalTime().Ticks}")); Console.Out.Flush(); } private static void WriteIncorrectReceipt(string change, ReadOnlySpan input) { // Explicit negative control: imitate an incomplete/corrupted child // receipt and exit zero before the real replay code can write one. // Nothing here calls or references the validator implementation. string[] arguments = Environment.GetCommandLineArgs(); int resultIndex = Array.IndexOf(arguments, "--result"); int targetIndex = Array.IndexOf(arguments, "--target"); if (resultIndex < 0 || targetIndex < 0) { throw new InvalidOperationException("Receipt negative controls require an isolated _replay child."); } var inputs = new JsonArray(new JsonObject { ["path"] = "fuzzing/ContractFixture/Corpus/NegativeControl/safe.bin", ["sha256"] = FixtureDependency.Hash(input) }); var receipt = new JsonObject { ["target"] = arguments[targetIndex + 1], ["type"] = typeof(ContractCallbacks).FullName, ["method"] = nameof(NegativeControl), ["inputs"] = inputs }; switch (change) { case "target": receipt["target"] = "other.synthetic.target"; break; case "type": receipt["type"] = "Synthetic.UnexpectedType"; break; case "method": receipt["method"] = "OtherMethod"; break; case "count": inputs.Clear(); break; case "extra": inputs.Add(inputs[0]!.DeepClone()); break; case "path": inputs[0]!["path"] = "fuzzing/ContractFixture/Corpus/NegativeControl/different.bin"; break; case "hash": inputs[0]!["sha256"] = new string('0', 64); break; default: throw new InvalidOperationException("Unknown synthetic receipt control: " + change); } File.WriteAllText(arguments[resultIndex + 1], receipt.ToJsonString()); } private static long s_spinIterations; } }