Last week, the US government released the report “Back To The Building Blocks: A Path Toward Secure And Measurable Software”. This report is part of the US Cybersecurity Strategy and focused on multiple areas, including memory safety vulnerabilities and quality metrics.
This report has been commented on by many online magazines, which have underlined the significant push back against the C and C++ programming languages.
Some of these articles include:
- White House urges developers to dump C and C++ by InfoWorld
- White House urges developers to avoid C and C++, use ‘memory-safe’ programming languages by Tom’s Hardware
- White House urges tech companies to adopt secure program languages by readwrite
Table of Contents
What does the US Government report say about memory safe languages?
The report focuses a lot on “memory safety vulnerabilities” and singles out “programming languages that both lack traits associated with memory safety and also have high proliferation across critical systems”. It continues recommending to “use memory safe programming languages at the outset, as recommended by the Cybersecurity and Infrastructure Security Agency’s (CISA) Open-Source Software Security Roadmap.
The reference is to the report NSA Cybersecurity Information Sheet on Software Memory Safety. This document goes into deeper details in terms of explaining what memory safety is, inducing it as a mix of type safety, safe allocation and deallocation (possibly with a garbage collector). This paragraph has the core content:
Using a memory safe language can help prevent programmers from introducing certain types of memory-related issues. Memory is managed automatically as part of the computer language; it does not rely on the programmer adding code to implement memory protections. The language institutes automatic protections using a combination of compile time and runtime checks. These inherent language features protect the programmer from introducing memory management mistakes unintentionally. Examples of memory safe language include Python®, Java®, C#, Go, Delphi/Object Pascal, Swift®, Ruby™, Rust®, and Ada. Even with a memory safe language, memory management is not entirely memory safe.
Does the NSA list Delphi as a memory safe language?
Yes, Delphi is listed as a memory safe language. Some of the articles initially reported a shorter list of safe languages, including only some of the most popular ones and excluding Delphi. The list has later been rectified matching the NSA report.
There has been some discussion in the Delphi community in terms of considering the language safe or not, considering it lacks one of the traits of memory safety, garbage collection. However, the official assessment was done on multiple grounds and taking into consideration other elements:
- One core feature of safe programming languages is having a strong type system and having the language verify the data types mapping at compile time, and not at runtime. Dynamic languages, even with a garbage collector, can fall short and be exposed to runtime errors, which can impact their safety
- The other element is not not having to resort to the use of pointers and more direct memory management in general code. While Delphi doesn’t block the use of direct memory access, this is fairly uncommon. Delphi offers mechanisms that automate and simplify memory management even without a GC.
Does using a memory safe language mean I am completely protected from security risks?
The other general consideration is that memory safety is presented as a goal but not an absolute. For example, the main report underlines that there are types of applications in which predictability of the execution timing is crucial (referring to the aerospace industry). These are scenarios in which a garbage collector kicking in at unpredictable times can affect the program execution of code with critical timing. Delphi has a significant advantage compared to other popular languages in the industrial automation space precisely for this reason. It allows direct control, while remaining at a higher and simpler level compared to C++.
The NSA and US Government lists Delphi as a memory safe language – what else does it recommend?
While the report recommends the shift towards memory safe languages, it also underlines the use of formal methods for static code analysis, in particular focused on security. We have been seeing a growing interest in this area also for Delphi, and we have been promoting third party tools that help in this space.
There is also a long section focused on hardware-based or CPU level enforcement of memory security. In the same area, the original NSA report underlines the importance of leveraging features like Control Flow Guard (CFG), Address Space Layout Randomization (ASLR) and Data Execution Prevention (DEP). Some of these security settings have been enforced in recent versions of Delphi and are now the default for new projects.
What is supply chain security?
Finally, there is another long area covering the security of the library dependency chain, also sometimes referred to as “supply chain security”, advocating the use of formal methods to assess libraries safety, including that of open source libraries. There is a growing concern that the high number of dependencies of many projects is expanding the security risk not due to the project code, but the libraries used. In this respect the report has a detailed description of the Log4Shell vulnerability in the Log4j Java library. This library vulnerability affected a memory safe language like Java and showed, in the report words, “a critical weakness through which malicious actors could compromise computer systems across the world”. The report continues indicating that “this vulnerability highlighted the critical need to help ensure the security of the open-source ecosystem, which fosters tremendous innovation worldwide.”
What is Embarcadero doing to help with security risks?
It is clear that there is a growing concern in terms of software security at all levels, from government bodies to businesses of all sizes. Even before the release of this White House and NSA report where Delphi was listed as a memory safe language, Embarcadero had already identified security as a growing concern among customers. We continue to focus on investing in and improving Delphi support for modern security techniques and backing that with clear hype-free education on the genuine risks and available mitigations.
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition
You claim that the NSA lists Delphi as a “memory safe language”, but I couldn’t immediately verify this claim. Could you please post a link to an official NSA document that makes this claim?
Sure, happy to.
Here’s a link to the official document: https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF as you can see, Delphi is listed on Page 6, 2nd line.
Thank you! (Google initially took me to all the wrong docs.)
It’s awesome to see Delphi being mentioned in these contexts!
Seriously, Google found the NSA doc in 3 seconds flat
Thank your for letting me know that.
When I searched, almost two weeks ago, my quick 2-minute effort (“immediately”) only gave me docs without explicit lists of “memory safe languages” or docs with the shorter list mentioned above (that doesn’t include Delphi).
I intentionally didn’t include “Delphi” in my search phrase, because I wanted to see if people looking for “NSA memory-safe languages” would find Delphi listed or not in practice.
And I did find NSA documents discussing memory safety, but they all listed Rust etc. without Delphi.
If 99.9 % of people find one version of the document (maybe linked from the NSA home page), not mentioning Delphi, that means something. (Even if technically there is some hidden version of the document including Delphi somewhere else.)
The NSA updated their document – the original version omitted Delphi even though their explanatory article included it. The document I displayed *is* the NSA document.
https://media.defense.gov/2023/Apr/27/2003210083/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY_V1.1.PDF
I wonder how Delphi is considered a memory-safe language: As a programmer it’s still my responsibility to deallocate dynamically-allocated object instances, or manage dynamic-sized arrays, in the code, preferably by using try/finally clauses, but it’s still quite possible to be careless when programing in the C/C++ style (total freedom and careless management of pointers or even handles for threads, events and sockets) if I want, though shouldn’t.
Delphi does not provide a GC (and I don’t want it!): I really prefer total control of what’s done with the dynamically allocated memory for object instances, buffers and the like… if there are errors, they are mine to detect and fix, I shouldn’t rely on the language.
So, I still wonder why Delphi is considered a memory-safe programming language when there is no GC, nor are there automatic safety-checks for buffer allocation/deallocation or memory management errors besides the warnings about the use of uninitialized variables… Or am I missing something?
The articles go into their methodology and how/why they consider something memory safe or not safe. The GC is not the only factor when it comes to their definition of safety. Other factors such as compilation, linking, flag setting, things like complying with modern practices like the randomization techniques and so on are all part of that.
You can, of course, write memory unsafe code with Delphi, but you do have to ignore all sorts of warnings and turn off various settings or generally *aim* to write memory-unsafe code. We’re going to be looking more at this in the future and also providing some webinars on code safety, and security/compliance/audit (which we’ve already begun to do) because it’s more and more a prescient topic. The ‘bad guys’ out in the world of technology get better and better and it’s very much an arms race – but, as you point out, it’s not just deliberate attempts to subvert that are the only problem: making the right code choices and things like SAST, SCA, and other types of analysis including supply chain is a whole rounded approach that needs to be understood and considered.
I don’t want to start a big debate, but I too was a bit surprised when I first learned about NSA considering Delphi to be “memory safe”.
Ian wrote,
“You can, of course, write memory unsafe code with Delphi, but you do have to ignore all sorts of warnings and turn off various settings or generally *aim* to write memory-unsafe code.”
which is true or false depending on your exact definitions of “memory unsafe”, “all sorts of warnings”, “various settings”, etc.
My first instinct would be to consider Delphi unsafe, because we all know that the majority of Delphi programmers are not very experienced, and so write code like
procedure StupidProc;
var
Form: TForm;
begin
try
Form := TForm.Create(nil);
Form.ShowModal;
finally
Form.Free; // if the ctor fails, will call the dtor on a “random” pointer
end;
end;
This does produce a W1036 warning, but still this pattern is frequently found in actual code. I regularly encounter this pattern in Stack Overflow Qs.
And there are many, many ways to end up with dangling pointers which can corrupt your memory in “random” ways (or give you an AV if you are lucky):
procedure StupidProc;
begin
var Y: TForm;
var X := TObjectList.Create;
try
X.Add(TForm.Create(nil));
X.Add(TForm.Create(nil));
X.Add(TForm.Create(nil));
Y := X.First;
finally
X.Free;
end;
Y.ShowModal;
end;
This is just one example. There really are a million other ways you can end up with such a dangling pointer. And you don’t get any warning. You really need to be careful about who owns what and exactly when a transfer of ownership occurs. You really need to be pedantic about your try..finally and try..except patterns.
Objects (TObject things) are core to Delphi, and they are fundamentally pointers that very easily can become dangling.
When I review Delphi code written by non-experts, it is more common than not that I do find issues that potentially can cause memory corruption or unintentionally reveal some contents of memory.
I realize there’s an enormous resistance to making changes to the Delphi language, but now that you can declare inline variables, it would be nice to have a notation that lets you declare an inline class variable (ie, an object instance) within a block in a way that tells the compiler to automatically delete it at the block’s ‘end’ statement as if it’s explicitly declared in a try…finally block. It seems like most of my memory errors come about because I add an object var somewhere and forget to add it to the finally clause (or the _correct_ finally clause) further down the page. There’s nothing syntactically wrong with defining a var, initializing it somehow, and leaving it intact for later use. However, unless the var is a global, or is set by calling a class method (not Create) that returns an object reference, the compiler should issue a warning when the var itself goes out of scope and never explicitly Freed.
In general, computers are supposed to make our life easier. But so little effort has been made over the years to reduce the effort needed to express solid, easy-to-read (and comprehend), and safer logic concepts written in Delphi’s code, that it seems like this is a strange topic for the Delphi vendor to be cheering about. Tracking down orphaned run-time objects in a Delphi app has always been a time-consuming effort that could be aided and/or alleviated by some simple syntactic changes to the language (with proper run-time support). Mentioning things like this may, at best, get them added to the end of a long list of things that would make the language more productive and safer that goes back well over a decade.
Also, the VA possibly has the largest extent of Delphi code of any single entity in the world: their front-end UI code is mainly Delphi and their back-end is all MUMPS, and this is mandated for most 3rd-party contractors and developers who write software for them. So it was somewhat humorous to see that Delphi was missing from the initial list, and then added later. Do you think the Government itself would actually come out and say, “BTW, one of our agencies is among the largest user in the world of an ‘unsafe’ programming language”? I’m guessing that’s the more likely reason it was included in the list. I posted something on a forum about how little use is made of explicit memory pointers in Delphi vs. pre-Dephi Turbo Pascal, and was pelted with people defending it use, claiming is not all that uncommon, and even people saying, “You obviously haven’t spent much time reading the source code for Delphi’s run-time libraries!” Well, *I* rarely use explicit memory pointers in my Delphi code, and I’m very happy that I don’t have to deal with the ^ operator very much.