It's a pretty standard argument: Utility A sells cheap service in area A. Everybody moves to area A. Utility hikes price of service by 10000%. Is everybody now supposed to move, or what?
In the analogy: software = service, area A = Microsoft Windows, and moving = changing platforms. For some people changing platforms is even more expensive than moving physical locations, and for others it's actually impossible (if they need Windows-only software to operate). Sure you could argue that they shouldn't have gotten so tied to the platform in the first place, but saying that doesn't actually help anything.
... something can keep you from writing insecure code. I just demonstrated one way to keep yourself from writing code which was vulnerable to SQL injection. You can use a similar trick to prevent yourself from writing a HTML/XML templating engine which allows quoting or cross-site scripting bugs. You can use a similar trick to prevent array index overflows while still permitting the elimination of most run-time array bounds checks (by 'blessing indexes'). In fact, this simple abstraction trick applies to most types of security problems which actually occur in practise. Just those three categories of security bugs probably cover more than 90% of all security issues which are typical today.
In more general terms: You write a small "kernel" which can be trusted (prepare_stmt in my example) and you've effectively forced yourself (and others if they use your module) to write secure code everywhere else.
It's getting late, but I'll just correct myself... from the WP article:
Once Whitman began facing return gunfire from the authorities, he used the waterspouts on each side of the tower as turrets, which allowed him to continue shooting while largely protected from the gunfire below, which had grown to include civilians who had brought out their personal firearms to assist police.
So it does mention it... however, you did put a very different spin on it.
Please cite your source for that claim of civilians helping to supress Whitman's fire. WP's Whitman article doesn't mention anything of the sort, and if you actually have a citation, it should be corrected.
type prepared_stmt = 'a
type result =... something concrete...
type parameters =... something concrete...
val prepare_stmt : string -> prepared_stmt
val execute_sql : prepared_stmt -> parameters -> result
end);
If prepare_stmt checks its input for dangerous SQL characters there is absolutely no way you are going to be able to cause an SQL injection as long as database modules adhere to this module signature (which is something the compiler can check statically).
Why? First and foremost because the ML language prevents you from doing things you shouldn't (your phrasing), namely violating the type system. Secondly because it's type/module system actually supports abstraction in useful and meaningful ways.
std::string is not secure. The standard does not mandate bounds checks on its operations; this is a consequence of the STL not mandating exceptions and many of std::stirng's functions returning references.
it's that difficult, at least from a technical perspective. As I see the problem is more of a social/practical one than a technical one. The fact is most drivers are written in unsecure languages (C or C++). All you need for safer drivers is a programming language such as Occam. Occam can make static guarantees about memory use, process isolation, etc. and you end up not needing hardware protection at all. Now, getting the whole world to change their compilers to output Occam instead of C/ASM isn't exactly easy, but it's a social problem, not a technical one.
(Of course, I'm not naive enough to think that this will actually happen, but I think it's worth pondering. And in the meanwhile we can be happy that hardware-based virtualization seems to be here to stay.:))
are compilers that have been proven to be correct (i.e. to adhere to the operational semantics of the language it compiles.). I can't remember the compiler offhand though, it's probably one of the ML ones. Of course that doesn't mean that there isn't a bug lurking somewhere in the C library that the compiler (or the runtime!) probably uses at some level.
I think Knuth said it best: "Beware of bugs in the above code. I have only proven it correct, not tried it."
Generally, a lot of the difficulty in proving code correct comes from the mainstream languages' adherence to the Turing Machine model, i.e. mutable state. If you program in a language with referential transparency, say Haskell, it suddenly becomes much easier to prove that your code is correct -- certainly not trivial by any means, but much easier. Some say it makes actual programming harder, but frankly I don't find it that hard since it almost automatically leads me to write more correct code. The reasons could be many, but I suspect it's mostly because it tends to force me to think more before actually writing any code. That and a vastly richer type system which lets me *gasp* embed proofs into my code. And the fact that you have to write less (boilerplate) code overall. And...
And every filesystem does have it - I never said that it's specific to one filesystem, though I was replying to a given filesystem.
The level at which error correction on a CD/DVD occurs is not the file system. I can do the equivalent of dd=/dev/HUGE_FILE of=/dev/cdwriter and error correction will still be applied. Of course you may have a different notion of what a file system is, but generally a storage layer isn't considered a file system unless you actually use it for organizing files... which the "sector level" (Yellow Book) layer of a CD/DVD doesn't do. (Of course you could stretch it and say that "tracks" are files, but that would just be silly words games.)
Again, ISO9660 does not contain any error detection/correction, nor does UDF. It's handled by the layer below it (Yellow Book CDROM Mode 1).
But that's not error correction for the data decay we're talking about with this article, aging.
That's immaterial to anything I said. My point was simply to correct the usage of the term file system and the misconceptions some people seem to have about error correction on CDROMs/DVDs.
It is an error correcting code -- IIRC one that's designed specifically to correct the types of writing errors which are common on optical media. Remember, correction does not imply that it can correct all media failures -- there is always some type of media failure which no amount of error correction can handle (say, destruction of the whole universe).
Also, the error correction/detection is not dependent on having any particular file system on the medium. Any data CD (regardless of file system) has the data correction built-in.
It's not really redundancy if you can't do without it.
You can do without it in the case of CDs and DVDs. It's just that the media and burning equipment would generally have to be of such high quality that nobody would be able to afford it. Think of it at as a cheper alternative to a perfect manufacturing process.
Yes, there are some things you cannot do due to this being a user-space implementation, but for many purposes it is (will be once it reaches 1.0) sufficient.
You would not have to download every patch. Patches could have separate metadata saying "Only install if a device with such and such device is installed" (and similarly for other stuff). The client software could then decide whether to download the full patch based on metadata. Yes, one would have to download all the metadata, but at, say, ~1k bytes per update that would not be prohibitive at all.
when a program is running, at least not on any reasonably modern kernel. Most (all?) current operating systems only load pages from executables on demand. If it doesn't get used it doesn't get loaded into memory.
DMCA. Those were found to be in violation of the anti-circumvention provision. Reverse engineering is still permitted as long as it isn't for the (sole?) purpose of circumventing protection measures.
The difference between C# and C++ with respect to parsing is that in C++ you can generate the full parser code at compile time (see Boost.Spirit) and have that code be optimized by the compiler; in C# the best you can hope for is to generate parsing tables at runtime and using a small static parser kernel for actually interpreting those tables. That is, in C++ you can get static guarantees whereas you cannot in C#. Furthermore, performance is likely better if you generate parser code instead of generating tables and using a small kernel of code to traverse/interpret those tables. (Disclaimer: I'm not familiar enough with C# to know whether one could generate 'custom' parser code at runtime using reflection. However, that would definitely not be for the faint of heart.)
That's not say C++ doesn't have problems: The template syntax is horrible, the standard library is... lacking if you "just want to get things done". However, the generic programming approach used by the STL is pure genius. Yes, it's verbose, but if you use iterators properly you can make all your code almost completely container-agnostic -- thus making tuning much easier. Unless you have _very_ tight constraints, Boost is also a must for any serious C++ project. In particular, shared_ptr, weak_ptr, function, bind() and boost::variant make C++ programming much more painless and safe. In my experience generic programming is also far superior to the OOP approach so blindly accepted by Java/C# users. And who knows, maybe we'll finally even get sane error messages for generic programs with C++0x;).
My own pet peeve is Metacity's refusal to remember the size or positioning of windows. I know the developers claim it's the application's job to do this, but I don't agree. Seems obvious to me, but who am I to insist that a window manager's job is to manage windows?
An X window manager does not have enough information to do this sensibly and reliably. Yes, you can do crude stuff like matching on window titles, but then what happens if you start multiple instances, or if windows have the same titles, or what if the app contains "embedded" windows (MDI style)? Hell, IIRC it's even impossible for a window manager to reliably determine if a window that has just popped up belongs to an application which has other open windows.
The code doesn't check for null after a memory allocation? Isn't the C++ standard to throw an exception instead of returning null when an allocation fails?
Memory allocations will almost never fail -- not even when the machine is actually out of memory (VM). Most modern operating systems use overcommit since many programs tend to allocate far more memory than they actually ever use; untouched pages need not have any backing. I should also note that Linux does allow you to turn this behavior off, but I'm not sure about other operating systems.
Anyway, in the unlikely event that a memory allocation should fail, I believe the behavior of C++ is to return null if exception support is turned off, and throw otherwise.
The links on the "readable" version are still incredibly annoying (dotted boxes) and the boxes are so distracting that you can't really focus on reading what the text says.
If that's your thing, that's fine, but just like the other poster I would close it after 1 second (even if it were to default to the "readable" version).
Viruses can also spread by email by exploiting buffer overflows in email clients. Good point about never underestimating the stupidity of developers (or their managers, who really knows?) though.
The argument that it takes ten years to become an expert at something ignores the distinction between the people who make very rapid progress at the onset and those who take years to get to that same point.
Rapid early progress really doesn't mean much for the total time to become an expert. As someone else pointed out, progress becomes exponentially harder the more you already know: Just picking rather arbitrary numbers it might take, say, 5 of those 10 years to take a single last "step" from "expert" to "master". That is, the difference in progress at the start may not mean that much when you get beyond "beginner" level -- since each stage becomes progressively harder it takes a (more) disproportionate amount of time -- and by that time the differences in progress at the onset will have been smoothed out. Yes, the person who progresses faster at the beginning may become an expert a year earlier than the others, but that still roughly ten years.
Btw, what's with this "exposure to music in utero"? Do have references to any credible papers to back that up? It sounds pretty ludicrous to me.
It would have been extremely silly to write the first LISP compiler in C when LISP interpreters were readily available at the time. The usual method of bootstrapping a language is to first write an interpreter for (a possibly simplified version of) the language, and then use that interpreter to develop/run the compiler until the compiler can compile itself.
There are other high-level languages besides the standard imperative ones, btw. Those languages typically have much stronger type systems (or computational models) that can be leveraged to provide higher-level optmization opportunities that are simply not possible in C for computability/decidability reasons. Granted, there aren't that many languages that actually do this today, but one example would be Occam where logically separate processes can be mapped to a single "hardware" process doing voluntary multitasking without violating process isolation and preemption at the logical level. This allows the system to replace expensive "hardware" context switches with two unprivileged instructions -- thus making running, say, 100000 threads on a single machine a pracical proposition.
It's a pretty standard argument: Utility A sells cheap service in area A. Everybody moves to area A. Utility hikes price of service by 10000%. Is everybody now supposed to move, or what?
In the analogy: software = service, area A = Microsoft Windows, and moving = changing platforms. For some people changing platforms is even more expensive than moving physical locations, and for others it's actually impossible (if they need Windows-only software to operate). Sure you could argue that they shouldn't have gotten so tied to the platform in the first place, but saying that doesn't actually help anything.
Interestingly laziness often makes Haskell code less efficent because of laziness. (TCO can end up forcing evaluation which isn't needed.)
In strict languages it's basically mandatory if you want to support functional programming styles (CSP, recursion instead of looping, etc.).
... something can keep you from writing insecure code. I just demonstrated one way to keep yourself from writing code which was vulnerable to SQL injection. You can use a similar trick to prevent yourself from writing a HTML/XML templating engine which allows quoting or cross-site scripting bugs. You can use a similar trick to prevent array index overflows while still permitting the elimination of most run-time array bounds checks (by 'blessing indexes'). In fact, this simple abstraction trick applies to most types of security problems which actually occur in practise. Just those three categories of security bugs probably cover more than 90% of all security issues which are typical today.
In more general terms: You write a small "kernel" which can be trusted (prepare_stmt in my example) and you've effectively forced yourself (and others if they use your module) to write secure code everywhere else.
So it does mention it... however, you did put a very different spin on it.
Please cite your source for that claim of civilians helping to supress Whitman's fire. WP's Whitman article doesn't mention anything of the sort, and if you actually have a citation, it should be corrected.
Why? First and foremost because the ML language prevents you from doing things you shouldn't (your phrasing), namely violating the type system. Secondly because it's type/module system actually supports abstraction in useful and meaningful ways.
std::string is not secure. The standard does not mandate bounds checks on its operations; this is a consequence of the STL not mandating exceptions and many of std::stirng's functions returning references.
it's that difficult, at least from a technical perspective. As I see the problem is more of a social/practical one than a technical one. The fact is most drivers are written in unsecure languages (C or C++). All you need for safer drivers is a programming language such as Occam. Occam can make static guarantees about memory use, process isolation, etc. and you end up not needing hardware protection at all. Now, getting the whole world to change their compilers to output Occam instead of C/ASM isn't exactly easy, but it's a social problem, not a technical one.
:))
(Of course, I'm not naive enough to think that this will actually happen, but I think it's worth pondering. And in the meanwhile we can be happy that hardware-based virtualization seems to be here to stay.
are compilers that have been proven to be correct (i.e. to adhere to the operational semantics of the language it compiles.). I can't remember the compiler offhand though, it's probably one of the ML ones. Of course that doesn't mean that there isn't a bug lurking somewhere in the C library that the compiler (or the runtime!) probably uses at some level.
I think Knuth said it best: "Beware of bugs in the above code. I have only proven it correct, not tried it."
Generally, a lot of the difficulty in proving code correct comes from the mainstream languages' adherence to the Turing Machine model, i.e. mutable state. If you program in a language with referential transparency, say Haskell, it suddenly becomes much easier to prove that your code is correct -- certainly not trivial by any means, but much easier. Some say it makes actual programming harder, but frankly I don't find it that hard since it almost automatically leads me to write more correct code. The reasons could be many, but I suspect it's mostly because it tends to force me to think more before actually writing any code. That and a vastly richer type system which lets me *gasp* embed proofs into my code. And the fact that you have to write less (boilerplate) code overall. And...
The level at which error correction on a CD/DVD occurs is not the file system. I can do the equivalent of dd=/dev/HUGE_FILE of=/dev/cdwriter and error correction will still be applied. Of course you may have a different notion of what a file system is, but generally a storage layer isn't considered a file system unless you actually use it for organizing files... which the "sector level" (Yellow Book) layer of a CD/DVD doesn't do. (Of course you could stretch it and say that "tracks" are files, but that would just be silly words games.)
Again, ISO9660 does not contain any error detection/correction, nor does UDF. It's handled by the layer below it (Yellow Book CDROM Mode 1).
That's immaterial to anything I said. My point was simply to correct the usage of the term file system and the misconceptions some people seem to have about error correction on CDROMs/DVDs.
Also, the error correction/detection is not dependent on having any particular file system on the medium. Any data CD (regardless of file system) has the data correction built-in.
You can do without it in the case of CDs and DVDs. It's just that the media and burning equipment would generally have to be of such high quality that nobody would be able to afford it. Think of it at as a cheper alternative to a perfect manufacturing process.
http://zfs-on-fuse.blogspot.com/
Yes, there are some things you cannot do due to this being a user-space implementation, but for many purposes it is (will be once it reaches 1.0) sufficient.
You would not have to download every patch. Patches could have separate metadata saying "Only install if a device with such and such device is installed" (and similarly for other stuff). The client software could then decide whether to download the full patch based on metadata. Yes, one would have to download all the metadata, but at, say, ~1k bytes per update that would not be prohibitive at all.
I was looking for the fake LOTR torrent and accidentally got the real one. Bloody annoying.
when a program is running, at least not on any reasonably modern kernel. Most (all?) current operating systems only load pages from executables on demand. If it doesn't get used it doesn't get loaded into memory.
DMCA. Those were found to be in violation of the anti-circumvention provision. Reverse engineering is still permitted as long as it isn't for the (sole?) purpose of circumventing protection measures.
is a useless driver when the main focus of your OS is security. Remember the local root exploits in NVidia's drivers?
The difference between C# and C++ with respect to parsing is that in C++ you can generate the full parser code at compile time (see Boost.Spirit) and have that code be optimized by the compiler; in C# the best you can hope for is to generate parsing tables at runtime and using a small static parser kernel for actually interpreting those tables. That is, in C++ you can get static guarantees whereas you cannot in C#. Furthermore, performance is likely better if you generate parser code instead of generating tables and using a small kernel of code to traverse/interpret those tables. (Disclaimer: I'm not familiar enough with C# to know whether one could generate 'custom' parser code at runtime using reflection. However, that would definitely not be for the faint of heart.)
;).
That's not say C++ doesn't have problems: The template syntax is horrible, the standard library is... lacking if you "just want to get things done". However, the generic programming approach used by the STL is pure genius. Yes, it's verbose, but if you use iterators properly you can make all your code almost completely container-agnostic -- thus making tuning much easier. Unless you have _very_ tight constraints, Boost is also a must for any serious C++ project. In particular, shared_ptr, weak_ptr, function, bind() and boost::variant make C++ programming much more painless and safe. In my experience generic programming is also far superior to the OOP approach so blindly accepted by Java/C# users. And who knows, maybe we'll finally even get sane error messages for generic programs with C++0x
An X window manager does not have enough information to do this sensibly and reliably. Yes, you can do crude stuff like matching on window titles, but then what happens if you start multiple instances, or if windows have the same titles, or what if the app contains "embedded" windows (MDI style)? Hell, IIRC it's even impossible for a window manager to reliably determine if a window that has just popped up belongs to an application which has other open windows.
Memory allocations will almost never fail -- not even when the machine is actually out of memory (VM). Most modern operating systems use overcommit since many programs tend to allocate far more memory than they actually ever use; untouched pages need not have any backing. I should also note that Linux does allow you to turn this behavior off, but I'm not sure about other operating systems.
Anyway, in the unlikely event that a memory allocation should fail, I believe the behavior of C++ is to return null if exception support is turned off, and throw otherwise.
The links on the "readable" version are still incredibly annoying (dotted boxes) and the boxes are so distracting that you can't really focus on reading what the text says.
If that's your thing, that's fine, but just like the other poster I would close it after 1 second (even if it were to default to the "readable" version).
Viruses can also spread by email by exploiting buffer overflows in email clients. Good point about never underestimating the stupidity of developers (or their managers, who really knows?) though.
Rapid early progress really doesn't mean much for the total time to become an expert. As someone else pointed out, progress becomes exponentially harder the more you already know: Just picking rather arbitrary numbers it might take, say, 5 of those 10 years to take a single last "step" from "expert" to "master". That is, the difference in progress at the start may not mean that much when you get beyond "beginner" level -- since each stage becomes progressively harder it takes a (more) disproportionate amount of time -- and by that time the differences in progress at the onset will have been smoothed out. Yes, the person who progresses faster at the beginning may become an expert a year earlier than the others, but that still roughly ten years.
Btw, what's with this "exposure to music in utero"? Do have references to any credible papers to back that up? It sounds pretty ludicrous to me.
It would have been extremely silly to write the first LISP compiler in C when LISP interpreters were readily available at the time. The usual method of bootstrapping a language is to first write an interpreter for (a possibly simplified version of) the language, and then use that interpreter to develop/run the compiler until the compiler can compile itself.
There are other high-level languages besides the standard imperative ones, btw. Those languages typically have much stronger type systems (or computational models) that can be leveraged to provide higher-level optmization opportunities that are simply not possible in C for computability/decidability reasons. Granted, there aren't that many languages that actually do this today, but one example would be Occam where logically separate processes can be mapped to a single "hardware" process doing voluntary multitasking without violating process isolation and preemption at the logical level. This allows the system to replace expensive "hardware" context switches with two unprivileged instructions -- thus making running, say, 100000 threads on a single machine a pracical proposition.