Serious question: How can a programming language be more or less secure than another? I am just a hobbiest, not a professional, so I am genuinely curious.
My dad who is a software engineer can’t even answer my question. But then he’s old and I’ve only seen this argument coming from the young bloods.
Concrete technical answer (one of many): imagine you have a list (“array”) of 5 numbers, and you try to print the 10th number in the array. A secure language will say “error! it’s a list of 5 numbers, there is no 10th one!!”. C will instead print some random garbage (whatever happens to be in the part of memory following the 5 element list), or maybe do something even crazier (try searching “nasal demon”), without indicating that anything has gone wrong. There are many other issues like this with C. You end up with programs going completely into the weeds, turning control over to attackers, etc.
Abstract philosophical answer: Secure languages like Ada and (hopefully) Rust are designed to help you ensure the absence of unwanted behaviours, rather than just the presence of wanted ones. If you want behaviour X, the goal of old languages like C was to make sure you could write a program in which X was present. That was a big enough challenge in the old days that language designers stopped once they reached that point. If you don’t want behaviour Y (let’s say Y is a security attack), it’s up to you to just write the program without behaviour Y. 50+ years of experience have shown that to be inhumanly difficult once the program gets complicated, so you really do need help from the language. Accountants invented double-entry bookkeeping 700 years ago for similar sorts of reasons: to keep small errors in complicated systems from sending the system into a nose dive.
Ensuring the absence of behaviours is the classic problem of proving a negative, so there are limits on how thorough the checking can be, and the technical features (like the notorious Rust borrow checker) can be difficult to use. But if you’re willing to endure a certain amount of pain and runtime inefficiency (requiring the program to do a little extra work at each operation to make sure the result makes sense, like the example of the 10th element of the 5-element list), you can make programs much safer than you can in C.
Does that help?
Added: Rust is getting some flak because it is pretty new, is still a work in progress, has various unmet goals, etc. It’s not fully baked yet but it is getting there (I’m studying it right now). Ada is an older language that is way more mature than Rust, but is more of a pain to use in many ways, so Rust is currently getting more attention.
It’s mostly about memory access. Modern languages throw errors if, for example, you try to reference an element of an array that is “outside the bounds” of the array. C does not - it gladly returns whatever memory address is past the end of the array. So the programmer has to check that the index is 0 <= x < array_size whenever they access a an array entry. That’s a pain - so they don’t.
Its about the type of operations the compiler allow you to do, more or less. Like sharing mutable references, that can be independently changed in a ‘hard to keep track of’- manner. Other factors the compiler tries eliminate include buffer overruns and int overflows e.t.c.
Rust for example sometimes makes trivial things a royal pain, see linked lists for example. It also has a gaping microdependency/supply chain attack prone ecosystem, and the compiler interface is also not stable (afaik, caused some issues in linux). There is also no spec.
I have experience of both, and i love both, but C is my fav. Its often trivial to imagine the codegen with C, and there are no shortage of quality compilers. The language is also small enough that implementing a compiler is actually feasible.
Serious question: How can a programming language be more or less secure than another? I am just a hobbiest, not a professional, so I am genuinely curious.
My dad who is a software engineer can’t even answer my question. But then he’s old and I’ve only seen this argument coming from the young bloods.
Concrete technical answer (one of many): imagine you have a list (“array”) of 5 numbers, and you try to print the 10th number in the array. A secure language will say “error! it’s a list of 5 numbers, there is no 10th one!!”. C will instead print some random garbage (whatever happens to be in the part of memory following the 5 element list), or maybe do something even crazier (try searching “nasal demon”), without indicating that anything has gone wrong. There are many other issues like this with C. You end up with programs going completely into the weeds, turning control over to attackers, etc.
Abstract philosophical answer: Secure languages like Ada and (hopefully) Rust are designed to help you ensure the absence of unwanted behaviours, rather than just the presence of wanted ones. If you want behaviour X, the goal of old languages like C was to make sure you could write a program in which X was present. That was a big enough challenge in the old days that language designers stopped once they reached that point. If you don’t want behaviour Y (let’s say Y is a security attack), it’s up to you to just write the program without behaviour Y. 50+ years of experience have shown that to be inhumanly difficult once the program gets complicated, so you really do need help from the language. Accountants invented double-entry bookkeeping 700 years ago for similar sorts of reasons: to keep small errors in complicated systems from sending the system into a nose dive.
Ensuring the absence of behaviours is the classic problem of proving a negative, so there are limits on how thorough the checking can be, and the technical features (like the notorious Rust borrow checker) can be difficult to use. But if you’re willing to endure a certain amount of pain and runtime inefficiency (requiring the program to do a little extra work at each operation to make sure the result makes sense, like the example of the 10th element of the 5-element list), you can make programs much safer than you can in C.
Does that help?
Added: Rust is getting some flak because it is pretty new, is still a work in progress, has various unmet goals, etc. It’s not fully baked yet but it is getting there (I’m studying it right now). Ada is an older language that is way more mature than Rust, but is more of a pain to use in many ways, so Rust is currently getting more attention.
It’s mostly about memory access. Modern languages throw errors if, for example, you try to reference an element of an array that is “outside the bounds” of the array. C does not - it gladly returns whatever memory address is past the end of the array. So the programmer has to check that the index is
0 <= x < array_size
whenever they access a an array entry. That’s a pain - so they don’t.Its about the type of operations the compiler allow you to do, more or less. Like sharing mutable references, that can be independently changed in a ‘hard to keep track of’- manner. Other factors the compiler tries eliminate include buffer overruns and int overflows e.t.c.
Rust for example sometimes makes trivial things a royal pain, see linked lists for example. It also has a gaping microdependency/supply chain attack prone ecosystem, and the compiler interface is also not stable (afaik, caused some issues in linux). There is also no spec.
I have experience of both, and i love both, but C is my fav. Its often trivial to imagine the codegen with C, and there are no shortage of quality compilers. The language is also small enough that implementing a compiler is actually feasible.