Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Sunshine And March Vibes (2025 Wallpapers Edition)

      May 16, 2025

      The Case For Minimal WordPress Setups: A Contrarian View On Theme Frameworks

      May 16, 2025

      How To Fix Largest Contentful Paint Issues With Subpart Analysis

      May 16, 2025

      How To Prevent WordPress SQL Injection Attacks

      May 16, 2025

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025

      Minecraft licensing robbed us of this controversial NFL schedule release video

      May 16, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      The power of generators

      May 16, 2025
      Recent

      The power of generators

      May 16, 2025

      Simplify Factory Associations with Laravel’s UseFactory Attribute

      May 16, 2025

      This Week in Laravel: React Native, PhpStorm Junie, and more

      May 16, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025
      Recent

      Microsoft has closed its “Experience Center” store in Sydney, Australia — as it ramps up a continued digital growth campaign

      May 16, 2025

      Bing Search APIs to be “decommissioned completely” as Microsoft urges developers to use its Azure agentic AI alternative

      May 16, 2025

      Microsoft might kill the Surface Laptop Studio as production is quietly halted

      May 16, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»CodeSOD: Compile It Yourself

    CodeSOD: Compile It Yourself

    August 26, 2024

    Today’s anonymous submitter, who we’ll call Sally, works on medical devices. As you can imagine, the development process for such devices is very strict. I mean, it should be, but we know that the industry has problems.

    Unfortunately for Sally, one of those problems is the tech lead on a project she is inheriting. Said tech lead is leaving, and Sally is coming on to replace them. The project is in C#, and Sally is the most experienced with the language, making her the obvious choice to step in.

    Now, the current tech lead had some concerns about the development cycle. You see, the whole process of writing code, compiling code, deploying that code onto hardware, and then running the code just took too darn long. If you wanted to iterate as fast as possible, you needed to skip some of those steps.

    internal static Action<InstrumentState> Compile(IEnumerable<Configuration.Rule> rules)
    {
    var code = string.Format(@”
    using System;
    using SomeCompany.SomeProject.Instrument;
    using SomeCompany.SomeProject.Instrument.State.Actions;
    using ConsoleState = StateMachine.Types.State;

    namespace SomeCompany.SomeProject.Instrument.State.Reducers {{
    public class Script {{
    private static bool _done;
    private static void Done() {{ _done = true; }}
    public static void Execute(InstrumentState state) {{
    _done = false;
    {0}
    }}
    {1}
    }}
    }}
    “
    , string.Join(Environment.NewLine, rules.Select((i, o) => string.Format(@”
    if (!_done) {{ rule{0}(state); }}
    “
    , o)))
    , string.Join(Environment.NewLine, rules.Select((i, o) => string.Format(@”
    private static void rule{0}(InstrumentState state) {{
    if ({1}) {{ {2} }}
    }}”
    , o, i.Trigger, string.Join(Environment.NewLine, i.Actions))))
    );

    var types = new[] { typeof(Console), typeof(InstrumentState), typeof(ErrorEventAction), typeof(ComponentId), typeof(global::StateMachine.Types.State) };
    var refs = types.Select(h => MetadataReference.CreateFromFile(h.Assembly.Location) as MetadataReference).ToList();

    //some default refeerences
    refs.Add(MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), “System.Runtime.dll”)));
    refs.Add(MetadataReference.CreateFromFile(typeof(Object).Assembly.Location));

    var parse = CSharpSyntaxTree.ParseText(code);
    var assyName = Guid.NewGuid().ToString();
    var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true, optimizationLevel: OptimizationLevel.Release);
    var compilation = CSharpCompilation.Create(assyName, new List<SyntaxTree> { parse }, refs, options);

    var state = Expression.Parameter(typeof(InstrumentState), “state”);

    Action<InstrumentState> y = (_) => { };
    using (var stream = new MemoryStream())
    {
    var result = compilation.Emit(stream);

    if (!result.Success)
    {
    var compilationErrors = result.Diagnostics.Where(diagnostic =>
    diagnostic.IsWarningAsError ||
    diagnostic.Severity == DiagnosticSeverity.Error)
    .ToList();
    if (compilationErrors.Any())
    {
    var firstError = compilationErrors.First();
    var errorNumber = firstError.Id;
    var errorDescription = firstError.GetMessage();
    var firstErrorMessage = $”{errorNumber}: {errorDescription};”;
    var exception = new Exception($”Compilation failed, first error is: {firstErrorMessage}“);
    compilationErrors.ForEach(e => { if (!exception.Data.Contains(e.Id)) exception.Data.Add(e.Id, e.GetMessage()); });
    throw exception;
    }
    }
    else
    {
    stream.Seek(0, SeekOrigin.Begin);
    var assy = AssemblyLoadContext.Default.LoadFromStream(stream);
    var type = assy.GetType(“SomeCompany.SomeProject.Instrument.State.Reducers.Script”);
    y = Expression.Lambda<Action<InstrumentState>>(Expression.Call(type.GetMethod(“Execute”), state), state).Compile();
    }
    }

    return y;
    }

    You know when the first line creates a variable code and it holds C# code, you’re in for a time.

    The first block of code here does a lot. It queries the rules object- a reference to our settings database- to generate a series of rule{0} functions, where the {0} is some name. The body of the function has a condition on i.Trigger (ensuring this rule only applies sometimes) and then has a body defined by i.Actions, which is just C# code living in our data source.

    We then populate an Execute function with calls to every rule{0} function we generated. These themselves are further gated by a _done check, meaning it’s possible for some rules to abort the processing of further rules.

    The rest of the code here is a set of interactions with the C# compiler. We parse and compile the C# code that we just munged together through string concatenation, emit that compiled data into an in-memory stream, and if it succeeds in compilation, we create a C# assembly based off that stream. That is to say, we generate and execute a library without leaving anything on the filesystem for further review. It all exists purely in memory.

    We then generate a lambda which calls the Execute function in that newly generate library, and return it, so that other callers can now use it.

    There are so many things wrong with this. Setting aside the code generation, the code that gets generated is complicated: a chain of statements where each has its own dedicated trigger condition and may be skipped based on a done flag. Just trying to analyze that for any non-trivial set of rules is hard.

    The code generation, however, is the real WTF. First, they were using a set of static analysis tools to try and maximize code safety. None of the code living in the settings database went through that. Second, the settings database was editable by customers. Doctors were expected to edit it. The very idea that you could change the code running on the device by editing the Settings database was a huge “No!” But the bonus of doing this all in memory means that if there were a breach, it’d be trivially easy for an attacker to cover their tracks.

    Now, there was no malice on the part of the tech lead. This was all just for personal convenience to speed up iterating on the code. It wasn’t an intentional security flaw- it was just clever.

    Sally raised this to her boss. He sighed, put his head in his hands, and was silent for a long moment. “We just signed off on doing pen-testing last week. They’re going to destroy us.”

    [Advertisement]
    BuildMaster allows you to create a self-service release management platform that allows different teams to manage their applications. Explore how!

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleAI Engineering is the next frontier for technological advances: What to know
    Next Article Discover Mindfulness, Leadership, and Professional Skills to Enhance your Career

    Related Posts

    Security

    Nmap 7.96 Launches with Lightning-Fast DNS and 612 Scripts

    May 17, 2025
    Common Vulnerabilities and Exposures (CVEs)

    CVE-2025-4831 – TOTOLINK HTTP POST Request Handler Buffer Overflow Vulnerability

    May 17, 2025
    Leave A Reply Cancel Reply

    Continue Reading

    How to Create a Meme Generator Using HTML Canvas

    Development

    I tested Samsung’s QD-OLED 4K monitor for gaming and work – and it was equally practical

    News & Updates

    PwC Releases Executive Guide on Agentic AI: A Strategic Blueprint for Deploying Autonomous Multi-Agent Systems in the Enterprise

    Machine Learning

    Coffee Night with the Banshee: A Story by Srinidhi Ranganathan

    Artificial Intelligence

    Highlights

    Databases

    Find and link similar entities in a knowledge graph using Amazon Neptune, Part 1: Full-text search

    May 7, 2024

    A knowledge graph combines data from many sources and links related entities. Because a knowledge…

    resticterm offers a UI for restic

    March 23, 2025

    Secret Level asked Microsoft about an awesome Halo and Doom crossover — “Crafting this impassioned letter of my childhood,” but Microsoft said: “Nah.”

    January 3, 2025

    CISA Rolls Out Next-Gen Learning Platform to Boost Cybersecurity Skills

    November 19, 2024
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.