I encountered such a thing a few years ago while still using the ext3 filesystem and an IDE (remember those?) drive. Here's what happened. I extracted a largish tarball to build QT-4 from source. All was going well until the compile failed on a C++ file since it yelped about a missing header. I examined the source file and saw this:
#include <uniste.h>Yes, one bit was flipped (should be unistd.h, of course). I edited the errant file and happily finished the compile. Curious as to what went amiss, I re-extracted the tarball into a partition on another drive (also IDE but on a different controller) and it was correct. That was readily visible and I caught it but I can't help but wonder how much silent data corruption has gone on through the decades on my various systems.
I got to wondering how noticeable flipped bits in binaries might be. So, I wrote a little Ruby program to flip a random bit in the cat command and see if the corrupted binary still runs:
#!/usr/bin/env ruby require 'tmpdir' require 'open3' $outPath = "#{Dir.tmpdir}/catmandu" $data = File.new(`which cat`.chomp, "rb").read $bits = $data.length * 8 $me = IO.read __FILE__ puts "The cat command is #{$bits} bits and #{$data.length} bytes long." def flipBit byte, bit = (rand*$bits).to_i.divmod 8 d = $data.clone d[byte] = (d[byte].ord ^ (1<<bit)).chr File.open($outPath, 'wb') do |f| f.write d f.chmod 0700 end return byte, bit end def runTest trial byte, bit = flipBit begin check, err, status = Open3.capture3("#{$outPath} #{__FILE__}") rescue => e end if check == $me && status.to_i == 0 && e == nil result = 'pass' trouble = '' else result = 'fail' err = e if e err = err.to_s.force_encoding("ASCII-8bit").tr("\n", "/")[0, 60] trouble = " status = #{status}: #{err}" end puts "#{'%4s' % trial}: #{result} : byte #{byte} #{bit}#{trouble}" result end if __FILE__ == $0 trials = (ARGV[0] || 50).to_i failures = 0 trials.times do |trial| failures += 1 if runTest(trial) == 'fail' end puts "#{failures} out of #{trials} failed." end
I found a much lower error rate than I expected. In one run of 1000 trials, it failed only 38 times. There was a little excitement, however. About half-way through, one of the failures took the form of an output loop, requiring me to kill the corrupted child process to allow the program to complete. Most of the failures are stuff like seg faults and load errors due to symbols not found or faulty binary file format.
I have a hunch bit rot in source code and script files probably shows up more readily than in most binaries. Although a flipped bit in a comment will probably not cause a failure, a similar error elsewhere is likely to cause a syntax error or some sort of not-found condition, as in your example.