I find that integrated tests in software projects go a long way to reducing rot. When something eventually invariably breaks due to some external factor, the test suite greatly reduces the time to identify and fix the problem.
If you can build a piece of software and run unit and integration tests on it, it is more or less rot proof. That's because all those tests lets one delete or replace components of the system without having to worry too much that the whole thing is going to break in some unknown way that won't be caught until it's in production.
Without a good suite, the larger the system gets, the more people get scared of doing radical things to it because they are worried about breaking some critical functionality. As far as the not being able to build aspect goes, the main threat here is relying to much on closed source software and/or libraries that go out of support that no one can find the license, or critical documentation for, or worse manifests some critical unfixable bug.
Id love to agree with this but my experience differs on modern stacks. We so often mock or stub APIs, use a web driver that's pinned to a certain version of WebKit, test against virtual dom, etc that it's hard to get real reliable test results that don't break all the time.
But I suppose that's the problem; we don't have the time to fix bugs related to the environment that crop up when no code changes so we insulate our tests from the environment by design.
Software doesn't exist in isolation. It interacts with its host OS, shared libraries, other programs, protocols, file formats and external systems. If it can't keep up then it effectively rots even though not a single byte of it has changed.
Software rots if you can no longer set up the exact tool chain and environment (compiler, build tool, OS version, external database, etc) required to build and run it. Even interpreted languages suffer from this problem as features are subtlely changed - by design or accident. It doesn't matter if your project is using an ancient version of VC++ or a two year old version of NodeJS. If it doesn't keep up with the latest releases of the tools then it's already got one foot in the grave.
I think this is an interesting argument for something like scheme (r5rs or r7rs-small) where you could hypothetically implement an interpreter later for the same code base with much less trouble.
Mind you, it probably won't perform well or do everything, but you can imagine it'd be easier than implementing an entire VM.
Unless it's video games.
People will write mountains of software to play an old video game.
Your claim does not really follow the standard meaning.
Bit Rot is usually defined as all the ways that software can appear to stop serving it's function despite remaining the same, in the sense of being the same bits (or bytecode or interpreted code) run by the same computer.
"the software does not actually decay, but rather suffers from a lack of being responsive and updated with respect to the changing environment in which it resides."
Edit: Not being able to recreate or modify a given piece of software would an example of the bit of your tools/environment and this is one (but the only) source of bitrot in a piece of code.
In a nutshell, we can only safely use it if we somehow know that the source string fits into the destination buffer. Those situations are few: basically, they involve fixed-length string literals being moved into buffers that are "obviously" larger. E.g. some widget_t object has a char name[256] field, and we initialize it by default with strcpy(new_widget->name, "<unnamed widget>"), or some bullshit like that. The literal is way shorter than 256 and nobody in their right mind will ever make it that long, or shorten [256] in widget_t so that this literal doesn't fit.
In situations when we don't know the length of the source string, there are two cases: it is going into some buffer that is already allocated, or else we will be allocating one. In either situation, we must measure the length of the source string, to test whether it fits or to determine how much to allocate for it.
In the case when the string doesn't fit into the target buffer, we cannot use strcpy, obviously, since it copies the entire string. We use some truncating-copying function, or we handle the situation in some other way (diagnose the problem and abort or whatever).
In the case when we allocate, because we have calculated the length, we still should not use strcpy to finally copy the string. We should use memcpy, because memcpy doesn't wastefully examine every byte to see whether it is null.
So the opportunities for a correct, non-wasteful use of strcpy are few.
You're correct about the problems, and I would always recommend strncpy over strcpy for safety, but it's not quite as limited as you portray: You only need to ensure an upper bound on the string length that will fit into your destination buffer. In addition to literals, this can also be guaranteed by copying a string that's already stored in a container that's smaller than the target, such as a fixed-size buffer or database field.
strncpy is strcpy's daft cousin that wastefully writes extra null characters---except when there is no room; then it neglects to null-terminate at all.
strncpy was not needed even in C90, because of sprintf, which is less clumsy to use, doing everything in one step:
People say that gets is fundamentally broken as an API, beyond repair.
However, gets could have been "rescued" in C by requiring every implementation to publish a constant, say in <limits.h>, which indicates a maximum of how many bytes (including null terminator) the gets function will place into the target buffer, and ensuring that gets observes this constant.
Indeed, evidently, there was talk of this, and supposedly Doug Gwyn proposed that simply BUFSIZ be re-used for this purpose.
With such a constant in place, programs using gets could be wrenched out of the jaws of undefined behavior by sizing the input array according to that constant, ensuring that there cannot be overflow.
Rather than introducing this requirement, in the end the function was simply removed from the language.
As jussaskin said, it can happen to them too. For example, VM/370 was among first virtualization schemes that could do all kinds of things PC/server virtualization bragged on later. Many key apps/OS's might be put in it. Yet, you'd be hard-pressed to run one of those with today's IT budgets if you couldn't afford a mainframe. Likewise, quite a lot of PC virtualization vendors came and went. The survivors occasionally have compatibility issues or corporations start going in different directions with less support of the older product. The product itself is often tied to a specific OS or HW combination that might go away.
One can use virtualization to help future-proof apps. IBM's System/38 (later AS/400, iSeries, and IBM i) did this for decades. However, to be fully future-proof (esp for vendor level), the virtualization SW/HW solution itself needs to be immune to the problem. That means legally, easily-cloned HW with same for software and virtualization layer. Closest thing maybe NOVA microhypervisor on Loongson-style OSS CPU with x86 emulation if it's x86 apps. RISC-V w/ virtualization support otherwise.
Guess what future-proof virtualization all the mainstream approaches aren't using, though? ;)
If devs have to download a VM running an old OS with old tooling, the barrier to entry is getting quite high. I wouldn't touch an OSS project that made me do that, I would assume it was effectively dead.
Even though the VM image and tooling may still be runnable, the world around it with which it must interact continues to evolve and can leave your software obsolete.
I think the big question with the storage space we've come into is... why don't we have all the toolchains/environments available? Why isn't having multiple versions of every dependency just part of how we do things now?
That's been my understanding as well. The cpu's used typically aren't powerful enough to do anything other than simple encryption in a reasonable amount of time. Ssl is generally out of the question. Someone please educate me if that's incorrect.
If this thing is capable of running OpenWRT, it can run some sort of SSL for what it needs. Might be tight and might have to not be OpenSSL, but it can be done.
Lesser-capable devices may have issues. But note that one way or another, the devices must speak some decent encryption to get on to WPA2 networks. Of course that's probably done in the Wifi hardware, but it still shows that it's not like we're living in the 1980s where we literally wouldn't have been able to afford the silicon in a consumer device. Hardware acceleration of SSL shouldn't be that hard to get a hold of, for instance: https://en.wikipedia.org/wiki/SSL_acceleration#Central_proce...
But more to the point: there is no purpose to SSL/TLS on an appliance because it will not have a valid certificate, hence it won't protect anything. You might as well just use WPA2-PSK.
If you're using a custom client-side app to access the device, which many of these things seem to do, you can create a CA for the devices, put the public cert for the CA into the app, and issue each device an individual cert at the factory signed by that CA. Then the app can be reasonably secure and assured.
I say only "reasonably" because defending against the "I cracked into the device and stole its cert" is pretty hard, but I'd submit, also not all that realistic a threat in this case. I'm really looking to defend more against "I bashed together some encryption so crappy I can hack this by making you visit a hostile web page" than "I want to use this lightbulb without the NSA knowing". (On that note, an SSL cert only valid to a custom app that your browser won't accept isn't all bad, it prevents that sort of thing.)
I mean, this it total pie-in-the-sky in terms of the ask I'm making here for security knowledge and willingness to do something correctly instead of bashing out some terrible, incorrect crypto with direct and incorrect use of the primitives. But it's possible.
Actually... I won't call myself an SSL expert per se, but one of the things that I find personally frustrating in dealing with some people is that once you do know what's going on, using SSL is often much much simpler than bashing together your own crap crypto. Any sensible SSL library has places to stick the CA certs. Generating them isn't that hard, more just tedious. Generating a big pile of certs at the factory and siging them isn't that hard. Even if you're very sloppy with your SSL usage, where you don't do a great job of protecting your core cert, where you use the root of the CA instead of an intermediate so the private key of the root is "live" in the factory, you don't set up a good revocation solution and you just set the expiration as far into the future as you can, because you probably haven't got a mechanism for updating them... even if you make all those errors, it's still better than just bashing crap crypto together, because it'll still resist more attacks than your crap crypto and it's not really all that hard.
But I have abundant experience that shows people would way rather futz around directly with RSA keys and HMAC and spend days and weeks scraping something together rather than even entertain the suggestion of doing it even half correctly. I don't fully understand it. Do other people find futzing with crypto that fun? I play defense a lot in security, but I honestly find correct crypto a royal pain in the ass and do everything I can to outsource it via SSL (which may not be perfect but isn't necessarily bad and has the advantage of being very defensible when people ask "what do you do to secure things") or NaCL or something. Is it just the psychological difficulty of admitting that you don't really know what you're doing with this crypto stuff? I dunno.
Nobody's going to invest money into flashing each device with an individual cert just to protect against an attacker MITMing a home user's home wifi network to turn off a lamp. And you'd have to bundle your own whole TLS stack and browser with the app just to get the CA validated; that's a lot of extra software engineering.
If the user really cares about security enough, they can buy their own real TLS cert and install the cert on the brick.
Ah, I meant to add to my list of bad practices sticking the same cert on every device. Sorry. To be clear, I'm saying you got me on that one. I missed that.
Of course, one person steals that cert and they've cracked the system wide open. But that's the default case for crap crypto anyhow, so what's the difference, except you spent about 10 minutes in the shell and passed some parameters to your library instead of spending.... well... anything more than 10 minutes futzing around with AES and RSA and so on?
Also, while I understand your use of "nobody" in the slangy English sense rather than the strict mathematical sense, I would point out that as these devices get more sophisticated, eventually they tend towards a manufacturing process that will do something to each one in the factory anyhow. For instance, if you're doing any sort of burn-in testing you've already done the vast bulk of the hard work it would take to also use that time to stick a cert on there. Yeah, your cheap knock-off Wifi light won't do that, but as the industry matures I think you'll see practices that would permit certs without much additional work.
I'm not a cryptographer, in my hobby project I used a port of nacl to AVR to do encryption. Such an IoT device doesn't need to process a large amount of data for encryption, it can be done on a 8bit uC.
What kind of latency is really an issue here? The payload isn't going to be large for lots of these IoT devices. If it takes a couple of hundred milliseconds longer to carry out the transaction is that really a big deal?
Maybe if you're talking about an Arduino (which is more of a micro controller than a full-on CPU). Anything resembling a real CPU definitely has the horsepower for SSL.
The ESP8266, which is popular for hobbyist IOT projects doesn't have enough memory to do SSL.
That's not to say that you can't do encryption though, just that you need to rethink how to do it, where the solution is not just unencrypted JSON APIs.