57

Are there any programming languages that are designed to be robust against hacking?

In other words, an application can be hacked due to a broken implementation, even though the design is perfect. I'm looking to reduce the risk of a developer incorrectly implementing a specification.

For example

Question

  • Is there a language that addresses many or most of these issues? It's acceptable for the language to be scoped for a particular use-case such as WebApps, Desktop, Mobile, or Server usages.

Edit: A lot of people addressed the buffer-overflow issue, or say that the programmer is responsible for security. I'm just trying to get an idea if there exist languages whose main purpose was to lend itself to security as much as possible and reasonable. That is, do some languages have features that make them clearly more (or less) secure than most other languages?

20
  • 5
    Would you accept any variant of Pig Latin as a valid answer?
    – MDMoore313
    Commented Apr 14, 2014 at 19:37
  • 1
    Well, I don't have experience w/ Ada, however I don't believe any programming language would have prevented heartbleed, and am prepared to defend that statement.
    – MDMoore313
    Commented Apr 14, 2014 at 19:48
  • 3
    @BigHomie You seem to be contradicting Tom Leek. Care to explain why a language with automatic array bounds checking and memory management wouldn't have prevented Heartbleed?
    – Brilliand
    Commented Apr 14, 2014 at 20:24
  • 1
    @Brilliand I did read his answer. To clarify I mean any language that allows the developer to access dynamic memory (allocate, copy, etc), which is what that function does. Simply put, the vulnerability is not a buffer overflow, neither due to array bounds checking. This is because the function that sends the heartbeat uses memcpy() and takes a pointer to the supposed 'payload' sent from the client, which in reality can contain anything, as we've seen.
    – MDMoore313
    Commented Apr 14, 2014 at 20:52
  • 1
    Also, rereading your question, this was not the result of buffer overflow, while they are close, I don't know if there is a term for this.
    – MDMoore313
    Commented Apr 14, 2014 at 20:53

11 Answers 11

55

The Ada language is designed to prevent common programming errors as much as possible and is used in critical systems where a system bug might have catastrophic consequences.

A few examples where Ada goes beyond the typical built-in security provided by other modern languages:

  • Integer range type allows specifying an allowed range for an integer. Any value outside of this range will throw an exception (in languages that do not support a range type, a manual check would have to be performed).

  • := for assignment = for equality checks. This avoids the common pitfall in languages that use = for assignment and == for equality of accidentally assigning when an equality check was meant (in Ada, an accidental assignment would not compile).

  • in and out parameters that specify whether a method parameter can be read or written

  • avoids problems with statement group indentation levels (e.g. the recent Apple SSL bug) due to the use of the end keyword

  • contracts (since Ada 2012, and previously in the SPARK subset) allow methods to specify preconditions and postconditions that must be satisifed

There are more examples of how Ada was designed for security provided in the Safe and Secure Booklet (PDF).

Of course, many of these issues can be mitigated through proper coding style, code review, unit tests, etc. but having them done at the language level means that you get it for free.

It is also worth adding that despite the fact that a language designed for security such as Ada removes many classes of bugs, there is still nothing stopping you from introducing business logic bugs that the language doesn't know anything about.

13
  • 1
    +1 for referencing the Safe and Secure Booklet
    – TruthOf42
    Commented Apr 14, 2014 at 19:28
  • 26
    And yet, all of Ada's safety didn't prevent the Ariane 5 failure. Commented Apr 14, 2014 at 20:45
  • 9
    This is a nitpick but it's not having two different operators for assignment/comparison that allows Ada to do that. After all, = and == are different, too. Python distinguishes = (assignment) and == (comparison), and "won't compile" (SyntaxError exception) when they are misused. I think the main point of using :=/= rather than =/== is to prevent typos. Commented Apr 14, 2014 at 21:35
  • 3
    @ChrisDown Of course not. That's simple comparison. if 'a' = 'b': on the other hand... Commented Apr 15, 2014 at 13:17
  • 2
    @RobertHarvey Doesn't matter, the engineers used a hardware system (happened to use ADA), designed for the Ariane 4 flightpath, where it worked just fine, and then tried to use it for something it was NOT designed for (Ariane 5 flightpath) - also the fact that they had to override anything just proves more to the point that they were aware of what they were doing and had to take active steps (because of the language) to do bad things
    – TruthOf42
    Commented Apr 15, 2014 at 15:22
56

Actually most languages are "secure" with regard to buffer overflows. What it takes for a language to be "secure" in that respect is the conjunction of: strict types, systematic array bound checks, and automatic memory management (a "garbage collector"). See this answer for details.

A few old languages are not "secure" in that sense, notably C (and C++), and also Forth, Fortran... and, of course, assembly. Technically, it is possible to write an implementation of C which would be "safe" and still formally conforms to the C standard, but at a steep price (for instance, you have to make free() a no-operation, so allocated memory is allocated "forever"). Nobody does that.

"Secure" languages (with regards to buffer overflows) include Java, C#, OCaml, Python, Perl, Go, even PHP. Some of these languages are more than efficient enough to implement SSL/TLS (even on embedded systems -- I speak from experience). While it is possible to write secure C code, it takes (a lot of) concentration and skill, and experience repeatedly shows that it is hard, and that even the best developers cannot pretend that they always apply the required levels of concentration and competence. This is a humbling experience. The assertion "don't use C, it is dangerous" is unpopular, not because it would be wrong, but, quite to the contrary, because it is true: it forces developers to face the idea that they might not be the demigods of programming that they believe to be, deep in the privacy of their souls.

Note, though, that these "secure" languages don't prevent the bug: a buffer overflow is still unwanted behaviour. But they contain the damage: the memory beyond the buffer is not actually read from or written to; instead, the offending thread triggers an exception, and is (usually) terminated. In the case of heartbleed, this would have avoided the bug from becoming a vulnerability and it might have helped to prevent the full-scale panic that we observed in the last few days (nobody really knows what makes a random vulnerability go viral like a Youtube video featuring a Korean invisible horse; but, "logically", if it not had been a vulnerability at all, then this ought to have avoided all this tragicomedy).


Edit: since it was abundantly discussed in the comments, I thought about the problem of safe memory management for C, and there is a kind-of solution which still allows free() to work, but there is a cheat.

One can imagine a C compiler which produces "fat pointers". For instance, on a 32-bit machine, make pointers 96-bit values. Each allocated block will be granted a unique 64-bit identifier (say, a counter), and an internal memory structure (hashtable, balanced tree...) is maintained which references all blocks by ID. For each block, its length is also recorded in the structure. A pointer value is then the concatenation of the block ID, and an offset within that block. When a pointer is followed, the block is located by ID, the offset is compared with the block length, and only then is the access performed. This setup solves double-free and use-after-free. It also detects most buffer overruns (but not all: a buffer may be a part of a bigger structure, and the malloc()/free() management only sees the outer blocks).

The "cheat" is the "unique 64-bit counter". This is true only as long as you don't run out of 64-bit integers; beyond that, you must reuse old values. 64 bits ought to avoid that issue in practice (it would take years to "wrap around"), but a smaller counter (e.g. 32 bits) could prove to be a problem.

Also, of course, the overhead for memory accesses may be non-negligible (quite a few physical reads for each access, although some cases may be optimized away), and doubling pointer size implies higher memory usage, too, for pointer-rich structures. I am not aware of any existing C compiler which applies such a strategy; it is purely theoretical right now.

25
  • 3
    The big problem with "don't use C" is interoperability with other languages. Pretty much any language supports writing a wrapper for C libraries. But you can't easily use say a Java library from C# or Python. Commented Apr 14, 2014 at 15:05
  • 1
    From what I've seen, poor coding can make any language insecure in the practical sense. Good coding can make most languages secure, even inherently "unsecure" ones. I'll also risk being flamed for suggesting that the higher level the language, the less secure it is as you are relying more on routines written by others, which can be subject to more subtle bugs. Or to put it another way, I've never had a box pop up on my computer informing me that my version of C is out of date & needs patching to fix security issues...
    – John U
    Commented Apr 14, 2014 at 18:56
  • 3
    But you had that kind of box about the "standard C library"... which is formally part of the language. Similarly, you never had a popup about the Java compiler being insecure, only the runtime support code.
    – Tom Leek
    Commented Apr 14, 2014 at 18:58
  • 3
    @JohnU I've also never had a box pop up and inform me that code I have written myself needs patching to fix security issues. In other words, that box doesn't mean, "Wow, another instance of my platform being unsafe!" It means, "Hey, part of my code just got fixed, and I didn't even have to do anything!" Commented Apr 14, 2014 at 21:39
  • 2
    @JohnU I don't know about flaming for it, but I do think your assertion that "written by others makes it more subject to subtle bugs" is flat out wrong. Code written by experts in the field that code pertains to is orders of magnitude less likely to have subtle bugs than stuff you wrote yourself. It's why you hear things like "Don't write your own crypto" "Don't reimplement standard library data structures".
    – corsiKa
    Commented Apr 14, 2014 at 21:58
16

Most programming languages higher level than C are much more secure when it comes to programming errors like Heartbleed's. Examples that primarily compile to machine code include D, Rust and Ada. It's not interesting to talk about just memory safety, in my opinion.

Here is a list of additional programming language features that (I think) make it much harder to write unsafe code. The first five features expand the compiler's capabilities in reasoning about your code, so you, a human being prone to error making, don't have to*. In addition, these features also should make it easier for a fellow human being, an auditor, to reason about your code. OpenSSL's source code is often described as a mess and a language stricter than C could have helped to make it easier to reason about. The last two features are about context issues that affect security as well.

  • A strict type system: Makes it easier to reason about program correctness. Eliminates certain input attacks.
  • Immutable by default: having immutable values as the primary data container means it is much easier to reason about the state of your program.
  • Disabled or restricted unsafety: Don't allow scary things such as pointer arithmetic (e.g. Go), or, at least only allow it if wrapped in big fat warnings (Rust). Note that a language lacking in pointer arithmetic completely is excluded for use in a huge number of applications that require low level access.
  • Compile time taint checking: expand the type system to allow identifying tainted values: values that depend in some way based on input. The compiler could then (conditionally) forbid operations with a tainted value that leak information to outside observers, such as branching on such a value. This could prevent or at least migitate certain classes of timing attacks. As far as I know, these are only available in static code analysis tools, and not in compilers themselves?
  • Dependent types: dependent types are a means to tell the compiler that "here is an Int whose values are between 2 and 87" or "here is a String of maximum length 12 containing only alphanumeric characters". Failure to meet these requirements results in compilation failure, and not a runtime failure with likely unsecure results. This feature is available in Idris and some theorem prover languages.
  • Absence of garbage collection: Garbage collection is a big problem for language safety - it creates garbage collection pauses in your program. These pauses leak information about the state of your program and allow timing attacks to happen. When the garbage collector is invoked is impossible (or at best incredibly hard) to predict as a developer, however, and subject to huge changes for even the smallest amount of code changes.
  • Performance, portability & interopability: It may be fine if you have need for a secure and slow program that only runs on the PowerPC platform, but don't expect anyone else to use it for a cross-platform TLS library. OpenSSL is popular precisely because it's fast and runs everywhere from obscure MIPS-based routers to massively parrallel SPARC servers and everything in between. Furthermore any program or runtime in the world can interface with OpenSSL as a library because it uses C calling conventions.

From my limited knowledge of languages, no language does all of these. Rust is an example of a language that covers many - it is strict, immutable by default, has restricted unsafety, does not require garbage collection and is quite performant and portable. Compile time taint checking and dependent types presently appear to be exotic features that require either additional static code analysis tools or new languages, unfortunately.

* See also: formal verification

9
  • That's a good list. Dependent types are a big deal. Haskell, with appropriate extensions (like Type Families) covers most of the list. The execution model is not so great for preventing timing attacks, though. Lazy evaluation is a "mirror image" of garbage collection.
    – nomen
    Commented Apr 16, 2014 at 5:44
  • Not all garbage collectors are stop-the-world types. There are incremental and concurrent garbage collectors.
    – Doval
    Commented Apr 16, 2014 at 11:47
  • My garbage collection comment is the most relevant example of creating unpredictability in your programs. It is unwise to create behaviour in your program that is undetermistic or unpredictable for you as a developer. The characteristics of this behaviour might give an attacker too much information. You can make your program unpredictable with garbage collection (whichever type of GC you use), lazy evaluation, concurrency and more things. In most garbage collected languages it is in fact unavoidable, which is bad.
    – DCKing
    Commented Apr 16, 2014 at 12:43
  • The garbage collector comment is unfair because GC languages prevent huge amounts of common vulnerabilities while side-channel attacks due to GC's are almost non-existent in real world. I've discouraged GC's for crypto or anonymity systems due to that weakness but they solve a lot of problems in regular apps. Not to mention you get plenty of solutions to problems you mention typing real-time garbage collection into Google incl commercial Java products.
    – Nick P
    Commented Jan 11, 2015 at 17:56
  • 1
    @NickP No. Memory safety is what prevents huge amounts of common vulnerabilities, not garbage collection. It just so happens to be that many garbage collected languages are memory safe: but garbage collection does necessarily not imply memory safety nor does memory safety necessarily imply garbage collection. Furthermore 'realtime garbage collection' is not a solution to any problem I mentioned, as even realtime garbage collectors create complex unpredictability within your programs. I agree that memory safe garbage collected languages are preferable over non-safe, non-GC'ed languages.
    – DCKing
    Commented Jan 15, 2015 at 15:54
6

In the general spirit of what you're asking, I think the E language (the "secure distributed pure-object platform and p2p scripting language") is pretty interesting, in that it is attempting to securely offer features/computation models not generally available.

2
  • 2
    could you provide a bit more detail ala the ada answer? thanks!
    – lofidevops
    Commented Apr 15, 2014 at 10:29
  • E is a safe by design against many things language joined with the object capability security model. That model can be used to implement many types of security policies and systems in a way that supports POLA. It also has support for distributed computing. Its backers, esp Combex, have thrown together secure chat in (100 lines?), made a secure browser, and made secure desktop prototype immune to many problems Windows has. So, I'd say it more than qualifies as a secure language. The implementation is where the dragons will be, esp reliance on Java.
    – Nick P
    Commented Jan 11, 2015 at 18:04
5

All current (meaning still updated) programming languages are designed to have as few inherent security flaws as possible, but at the end of the day it's (almost always) the programmer who is responsible for security flaws, not the language he's using.

EDIT: As @DCKing pointed out, not all languages are equal, and I'm not saying it's a good idea to pick one at random and try and make it work. I am saying that a (very) talented C programmer can make a program just as secure as a semantically identical program written in a higher level language. My point is that we should recognize that some languages make it easier to make mistakes, but also know that in the end it's the programmer's mistake, not the language's (with few exceptions)

14
  • 4
    That's not the what's asked, though.
    – Ven
    Commented Apr 14, 2014 at 15:14
  • 4
    @user1737909 It answers the question. All programming languages are designed not to be inherently insecure, but that doesn't matter because it's how the programmer uses them that determines how secure a system is.
    – KnightOfNi
    Commented Apr 14, 2014 at 16:03
  • 7
    @KnightOfNi I feel like this answer is equivalent to saying that a castle is only as secure as the soldiers defending it, which is partly true, but there's a reason why castles were designed the way they were, so it's easier to defend and less work has to be done by soldiers
    – TruthOf42
    Commented Apr 14, 2014 at 19:46
  • 1
    @TruthOf42 Well, "a programming language in which the programmer does less work" is just a higher level programming language. Continuing with your castle analogy, the question is "what type of rock is best for my castle walls?" The answer is that unless you're using chalk, no one is going to go for your walls (in a majority of cases), they'll exploit the fact that you (the architect) forgot to add a door to the castle or left in a secret passage. It's almost always systems that are exploited, not languages themselves (with, obviously, a few exceptions).
    – KnightOfNi
    Commented Apr 14, 2014 at 20:36
  • In my analogy The Castle is the language, and the soldiers are the program. If you design a Castle with a very large entry way it's harder to defend, but if you design a castle where only one person can enter at a time it makes it easier to implement a policy that that ensures the person entering is authorized. What I'm trying to get at is that you can design a language is such a way that ENCOURAGES good security practices.
    – TruthOf42
    Commented Apr 14, 2014 at 20:46
4

There is no such thing as a secure language. If a language provides enough security for your problem depends a lot on the problem you are trying to solve. Like if you are writing a web application the security of most languages used in this context (e.g. Java, PHP, JavaScript... add your favorite) is enough to prevent things like buffer overflows, but even the more strongly typed languages don't offer inherent support for web specific things, e.g. like making it impossible or at least hard to introduce Cross-Site-Scripting bugs or similar. And no languages will protect you against a bad trust model, like trusting DNS servers (DNS rebinding etc), the current PKI model or by including third party (e.g. out of your control) scripts into your web application (typically ads or google analytics).

So the choice of a proper language might help you a bit, but there is not magic security sword.

9
  • +1 for "magic security sword." And all of the other stuff too :)
    – KnightOfNi
    Commented Apr 14, 2014 at 23:43
  • There is no language that is "secure" because "secure" is never probably defined (and not definable). There are languages that are more secure than other languages however given some threat model, and I think that's what this question is about.
    – DCKing
    Commented Apr 15, 2014 at 17:30
  • By the way, what do you mean with "more strongly typed languages don't offer inherent support for web specific things"? I fail to see how strongly typed languages don't offer that support or even how they are worse at supporting those features!
    – DCKing
    Commented Apr 15, 2014 at 17:32
  • They are not worse, but they don't provide inherent support for various kind of strings (html, javascript, css, url...) and make sure that everything gets escaped in the right way if you concatinate different types of strings (the rules are tricky and sometimes browser dependend). So right now most developers do it by hand or with some help of a toolkit but often do it wrong and cause XSS attacks. You can probably implement it, but right now there is at least no inherent support in the major languages used for web development. Commented Apr 15, 2014 at 17:57
  • @SteffenUllrich: look up Yesod. Oh, wait, you're moving the goalposts. "Major languages used for web development" don't have strong type systems.
    – nomen
    Commented Apr 16, 2014 at 5:40
4

Remember that for most programming languages, you have to worry about the security of two languages. There's the language you're actually using, and then there's the language that the compiler or interpreter are written in, which is often different. (Technically, there's a third, which is the microcode of the CPU itself.) A security issue in either of those languages can make your program insecure.

4
  • 1
    I thought all the cool kids were supposed to write the compiler of their language in that language.
    – Superbest
    Commented Apr 15, 2014 at 6:19
  • Most native code compiled languages are self-hosting (implemented in themselves). However, most popular languages these days are hosted in a VM which makes that impossible. You can still write a source-to-bytecode compiler in that language (e.g. javac) but the VM that interprets the bytecode has to be native code.
    – Nate C-K
    Commented Apr 15, 2014 at 14:27
  • 1
    However, I'd much rather worry about buffer overflows only in the code of the JVM itself instead of worrying about them in every single library my code depends on.
    – Nate C-K
    Commented Apr 15, 2014 at 14:29
  • Good point. Hence the importance of all the "certifying" compilation, interpretation, and memory management research. I think co-simulation is one of the better solutions. You create a model of how the source and target language do things. Run data through each one to obtain execution traces. Compare properties of traces to ensure they match in function and risk. One project is using this technique successfully for a C to MIPS optimizing compiler.
    – Nick P
    Commented Jan 11, 2015 at 17:47
3

Firstly, you do not actually write programs in programming languages. You write instructions for the compiler which describe what kind of program you want, and the compiler produces a program, in its own peculiar way, which will hopefully (if your compiler is well-designed) do the same thing that your source code describes. All programs, when they are running, are in "machine language" - they are a series of numbers that are interpreted in a certain way when loaded into RAM and fed into the CPU. Machine language is not designed with robustness to hacking in mind, so no language that is compiled can be truly "resistant" to hacking, because the actual program will be in machine language anyway. Any interpreted or VM language will still run in a native framework which is compiled ultimately to machine language, so the problem still persists.

Second, most real languages are Turing complete. This means that any task that can be accomplished by one of them can be accomplished by all. Therefore, you cannot make "hacking" impossible (if hacking means writing malicious programs); it would break the Turing completeness.

It's worth clarifying at this point what you mean by hacking. Since you mention Heartbleed, I imagine you don't mean it in Stallman's sense ("playful tinkering").

If you mean people who write programs that directly access the memory and steal data, or modify other programs (such as viruses or keyloggers) then this is not a problem a language can really deal with. A compiler can help, by having an additional function to produce obfuscated machine code when compiling, but ultimately it's still possible for a skillful memory hacker to find his way around. The solution to this problem is OS design: An operating system should sandbox programs, and not allow one program to mess with memory that belongs to another program. This is part of what UAC in Windows does (although Sandboxie is a better example).

There is a caveat here: Some languages, like C# or Java have features (more correctly, the compiler and the VM that the programs run inside have features) that check whether any program is trying to muck about in another program's memory, and when this happens throw errors like IllegalAccessException (for example, keylogger.exe should not be able to read the Credit_card_number value from internet banking application.exe). Of course, this requires keeping track of what memory belongs to what program, which has some non-trivial performance and effort cost. Some "simpler" languages like C don't have it - this is why a lot of hacks like viruses are written in C. Nowadays you have to be clever about evading UAC, but back in the days of Windows 98 people could do all sorts of crazy things to your computer/OS by reading and writing to memory they weren't supposed to. Note that even in C# you still have the option of using normal, C-like pointers (which the languages calls unsafe and requires you to mark as such in the code) if you want - although CLR will probably contain your hack within itself, unless you find a security hole in the CLR that lets you tunnel out into the rest of the memory.

The second kind of hacking is exploiting a bug in an existing program. This is the category heartbleed belongs to. With this, the question is whether the programmer makes a mistake or not. Obviously if your language is something like Brainfuck or Perl that is very difficult to read, it is likely that you will make mistakes. If it is a language with many "gotcha"s like C++ (see "classic" if (i=1) vs. if (i==1) or the C obfuscation contest) then it may be difficult to catch mistakes. In this sense, designing for security is really just a trivial special case of designing to minimize programmer error.

Note that the Heartbleed bug, whether deliberate sabotage or honest mistake, was a problem with the algorithm used (the author "forgot" to check the size) - so no compiler short of an AI as intelligent as a very smart human could possibly hope to detect it; although the resulting access violation conceivably could have been caught with some clever memory management.

In conclusion

There are two sorts of concerns with regard to hacking:

  1. A program has been programmed erroneously, and allows you to do things that you shouldn't. Eg. Gmail server lets everyone see your emails, instead of requiring them to enter the correct username and password first, because someone made an error when developing the server software. Includes bugs, vulnerabilities, etc.

  2. A program is manipulated by the hacker's malicious program. Includes viruses, keyloggers and other malware.

(1) can be fixed by making a language more strict and explicit, so that detecting errors is easier, but ultimately only very simple errors can be detected by automated tools, and as for "tripwires" like Ada's range checking, it can be argued that recognizing the possibility of an error is necessary for you to think of adding the check in the first place, and recognizing the possibility is already the hardest part.

(2) cannot be fixed by changing the language. If you make a language in which it is very difficult to write nefarious applications hackers will simply use another language, and will have no added difficulty manipulating programs written in your language because they are ultimately run as machine code anyway. It can be fixed by making an OS that very vigilantly polices programs running in it, but then it becomes a question of (1) type problems in the source code of the OS.

10
  • 2
    Turing completeness basically means a language can emulate any other computer (=> program => compiler => language feature) in existence. It doesn't mean a feature you're emulating can ever be as powerful, or as exploitable, as if it were native to the language. Java being a prime example -- you could emulate pointers using an array and int "pointers", but you'd still have to intentionally write code to allow a buffer to overflow. And it wouldn't affect anything outside the array.
    – cHao
    Commented Apr 15, 2014 at 13:09
  • 2
    First sentence is wrong. You do write programs in a programming language. The compiler translates that program into the same program in a different language.
    – Nate C-K
    Commented Apr 15, 2014 at 14:18
  • 2
    This answer completely misunderstands what programming languages are about. Higher level programming languages exist to make the generated machine code better
    – DCKing
    Commented Apr 15, 2014 at 17:22
  • 1
    So many bad claims. Higher level programming languages exist to make the generated machine code better in some way - e.g. more secure. If your higher level language guarantees that your generated assembly doesn't allow for certain insecure conditions at runtime, your language is more secure. Secondly, as pointed out, you completely misunderstand what Turing completeness entails. Just because Turing completeness is there for a developer, it does not mean it's there for an attacker. Lastly, local access to binaries is not part of the threat model for most attacks, including those on OpenSSL.
    – DCKing
    Commented Apr 15, 2014 at 17:27
  • I'll admit that some of my claims aren't exactly true - I deliberately wrote them in this way to keep things simple and concise. I think it is easy to see which ones, and it is easy to find out the correct version. However, I think the points I made are valid: For instance, Turing-completeness is a relevant concern if you would like to forbid certain kinds of programs by design. It depends a bit on how you define hacking: If hacking is deliberately (by tampering) or accidentally (bugs) creating a dangerous program, then does Turing completeness not guarantee the possibility of such a program?
    – Superbest
    Commented Apr 15, 2014 at 18:39
3

There are many secure languages. I would say that a language with memory management and thread safety is as secure as a language can get.

However, most of these are inefficient. Garbage collection is expensive, and interpreted languages more so. And that's why large applications to this day are written in the memory-unsafe C/C++.

I've recently been playing with Rust, and to me it seems to be a "secure" language in the sense that it was partly designed for this.

It's a compiled language like C++, and it also offers pointers and concurrency. (Garbage collector not necessary)

However, it doesn't lug the memory safety of pointers and concurrency with it. Rust is a language that doesn't trust the programmer, and at compile time it checks for suspicious usage of pointers. There are multiple kinds of pointers/references (borrowed, owned, etc), and some of them have strict rules about them. For example, one cannot:

  • take a reference to an owned pointer and then mutate the owned pointer
  • pass a reference to outside the lifetime of an object (references aren't just numbers that can be batted about like in C++)
  • move around an owned pointer and access the original variable

There are similar rules that ensure thread safety. If one wishes, they can bypass a lot of these checks by using unsafe-marked boxes ("trust me, I know what I'm doing"), or slow garbage collected pointers. There are also more Rustic (and efficient) ways of doing this by using a combination of clones and references, which vary as the usage changes.

1

Managed type safe languages do a lot to prevent this kind of thing by providing validation of types automatically and moving code execution further from the CPU itself, however that doesn't rule out the possibility of bugs in the implementation of the system the language uses to map to the CPU (for example, the CLR in .Net or the JVM in Java). It also doesn't rule out the possibility of bugs in an application that could cause it to be vulnerable to manipulation or data leakage for itself.

They do improve the security of the system quite considerably, but they also are bulkier, slower and more limited in function due to the overhead of the execution engine they have to run through to provide that functionality.

4
  • Type-safety has nothing to do with Virtual Machines like JVM or CLR, you could easily have a compiled language with type-safety. And having a compiler enforce array bounds checks is... easy. It does add a little overhead, but then again why do you want to write assembler? And sure, compilers are also programs and can have bugs, but at least there are languages with strict formal definitions that a compiler can provably fulfill (or not).
    – kutschkem
    Commented Apr 14, 2014 at 15:16
  • @kutschkem - yes, but MANAGED type safe languages do. Managed code requires something to do the managing. By the way, I'm also not speaking against managed languages at all. I'm a C# developer. Commented Apr 14, 2014 at 15:20
  • @kutschkem: A fundamental requirement for safety is being able to ensure that no object's memory will be subject to reclamation while any reference could exist to it. Requiring that all references be stored at all times in a way that the memory manager knows about can greatly facilitate this, and using a managed VM greatly facilitates that.
    – supercat
    Commented Apr 14, 2014 at 22:05
  • A compiled language can easily manage references and do garbage collection without requiring a VM. What's more, such a language can be implemented in itself, so you don't have to worry about C-related bugs in the C code used to implement your VM.
    – Nate C-K
    Commented Apr 15, 2014 at 14:23
0

There are certainly languages that were designed to be secure, but none that are perfect. For example, Ada allows you to specify an allowable range for integer variables and throws an exception if they ever go outside that range. Sounds good, saved you having to manually check. The problem is if you don't have to manually check it is easy to set this mechanism up and then forget to consider the consequences, i.e. integer out of range exceptions. You just created a vector for denial of service attacks.

Security is a process. The language can help, but at best it can only reduce the chance of errors an in the process usually creates new and often even more subtle ones. Arguably C, by nature of being easier to fully understand and fully deterministic operation (no background garbage collection, for example), is ideal for writing secure code. And sure enough, when you look at a lot of security critical code it is written in C. To be fair to Ada, it is more about reliability than security.

1
  • 1
    C is far from ideal: it's too complex, has undefined behavior, and has security issues in most common constructs (eg arrays, strings). Pascal and Modula-2 are much better for analysis due to simplicity, readability, consistency, and easy compilation.
    – Nick P
    Commented Jan 11, 2015 at 17:51

Not the answer you're looking for? Browse other questions tagged .