strncpy(dst, src, strlen(src));
dst[strlen(dst)] = '\0';That line alone is cancerous.
The way a string is terminated in C is by a null character. ‘\0’ is a mnemonic. strlen() returns the length of a strong. It does this by doing a linear scan down the array until it finds the null, and the returns that index as the length.
That line of code does nothing useful. It means, “scan through the array until you find a null, then write a null there.” Which is exactly what you had to start.
So why would someone write this? Well, they were told to make sure that you always terminate your C strings with a null, otherwise you’ll run off the end of the array and corrupt memory. This is true, but this isn’t how you need to find the end of the array. They should have used the number from strlen(src), not strlen(dest). Even worse, strncpy() will put the null terminator in dest in this case.
The line belies any sense that the programmer had any understanding of what the code was actually doing. It’s a amateur mistake.
It has to be the size of dst, which can only be known at the site of allocation in C (except for a non-clean way of looking at heap metadata).
It never makes sense to use strlen() for an argument to strncpy(). Only the size of the destination buffer makes sense for strncpy() (usually sizeof(dst)). For other cases you would probably use memcpy().
I thought the point was that they didn't know if the dest is long enough to copy source, so they copy as much of it as they can.
The reason for the '\0' is in the case that src is shorter than dest.
A more explicit way may be to strlen dest > src then just use lenght(src) otherwise use str(dest).
But this might actually be more efficient.
Edit: And in this case Spolsky doesn't apply because it seems the developer doesn't get to allocate the dest length.
If dst is larger than src, the strcpy* family of functions will also copy over the null byte.
If dst is shorter than src, and if strlen(src) is used as arg for strncpy then the function will overflow in dst and your null byte will also be outside dst buffer. In hardened environments you wouldn't trust strings to contain null byte if it comes from network or user and use strlcpy with known size of dst then append a null byte at end of dst anyway to ensure it is null terminated.
Using strlen to compare buffer sizes is totally wrong and is the source for many bugs (hint, strlen doesn't actually return size of anything but the distance of the first null byte from the address you provide it).
[1] https://www.joelonsoftware.com/2001/12/11/back-to-basics/
This is the real problem. That PM of course wants the work done yesterday and has ego issues so even when the contractor does question it they just double down on what they originally said.
Do we know that the developers were outsourced or which countries they were from?
IBM sold a big outsourcing package to a major European insurance company: they would move ALL their stuff to the IBM Cloud (VMWare with a lot of custom BPM workflows to handle provisioning, etc.). None of this matched their other three big cloud projects, Bluemix, Softlayer, or their OpenStack project (Zenith -- my prior project), so it was all new from the ground up.
They needed to handle mass imports of DNS data from this insurance company (~1 million hosts) and other customers and they brought me in as a senior developer to do the grunt work. Since we were using ISC bind, I assumed we could use features like exporting zones with signed requests and take advantage of all the infrastructure work put into that server to scale up. Our Senior Architect poo-pooed that plan, so I started modeling the DNS records as structured data for consistent and complete import and export. Our senior architect also nixed that idea and said that we're gonna load the DNS structures with REST requests: the support people were gonna have a custom web application to load simple DNS export files (not zonefiles, mind you) into this system, and to make ad-hoc additions and changes. (When we had a new developer join, he had the same questions I had about why we weren't using all the DNS bind features since they were done and tested and perfect for our needs . . . it took a month to get him to stop asking.)
I got about 90% of the way through a solution with a Python Flask REST server at the center, high code coverage through unit tests (because it's Python and I was still finding edge cases that needed fixing to the very end), and Rabbit MQ for enqueuing the changes we've received before writing them out to DNS zone files. It works, but we certainly didn't need to blow April to August building out the architect's vision.
The reward I got was being pulled off the project when it was nearly code complete and would shortly go into production. I got a team based in India to manage in the mornings, while my afternoons and evenings were returned to developing Javascript for the BPM infrastructure jobs.
(When told I was going to leave for another company, IBM's counter-offer was to move me from my remote work-at-home location in Ohio, near family, to the Cloud Managed Services office in Rochester, MN, and then consider a raise.)
This is pure thedailywtf material.
I get that you do need specs but c'mon, if you ask a plumber to fit a pipe from A to B and he uses one made out of cardboard would you think it was reasonable for him to say "well you didn't specify it had to carry water, pay me 3x as much to put it right". And then you find out that this is the first time he's even seen a pipe, but his business card says "senior plumbing expert".
You expect a basic level of competence and familiarity with the problem domain and good faith from any professional whose services you hire.
Also consider that a program is a spec, and if you are going to explicitly specify every little detail then you might as well just write the program yourself, there is literally no sane reason to put an outsourcer in the middle.
A responsible developer is expected to ask insistently until the requirements make sense; whoever delivered the JSON DOM is stealing their pay, even if they did it knowingly as a joke or provocation.
what i got was:
yes, their json interface was the DOM, serialized as json. but it gets better. to submit my data i had to fill in the actual values in their json struct at the appropriate nodes and send it back.i'm a) pretty sure this "json interface" feature cost the customer more than i make in a year, and b) it probably broke the very instant the customer let a frontend/designer guy change the html code months later.