Why does fgets() require a maximum size of user input?
To limit the amount of data that is saved - preventing buffer overflow cases.
Why specify the size?
To prevent fgets() from saving too many characters.
It also stops reading characters.
fgets() could have read excess characters in a line and not save them, yet the design is to read up to size - 1 characters and save them and then append a null character. If the buffer fills without a '\n', the rest of the line remains to be read.
Is it to prevent buffer overflow of some sort?
Yes, this prevents a buffer overflow. It also stops the reading of characters from the file.
Or is it just a design flaw?
It is by design as a limiting alternate to code like gets() (no longer parts of the C library) and scanf("%s", ... which remains risky.
Other (and later) functions that specify the buffer size are of type size_t. fgets() with its int size is a minor design flaw.
and in a security context, is this a risk?
Passing in a limiting size reduces risk.
Is the size a limitation, and in this context, prone to segfaulting?
The size reduces segment faults.
Reading a line in C is only partially handled by fgets().
Issues remain (some are pedantic):
How to detect and handle when not all the line was read?
Quieting unsigned_to_signed warnings that come up when a size_t variable is passed as the size.
Detecting the number of characters read when fgets() unusually reads a null character as strlen(), to find the number read, will stop on the read null character and not the appended one.
Many applications do not want to save the '\n'. So when the destination is size n, code needs additional helper code to read and save up to n-1 characters and then lop off the possible '\n or maybe still read if the buffer was full.
There are 4 reasons why fgets() stops reading: '\n' read, full buffer, end-of-file detected, rare input stream error occurs. Additional code must be careful to discriminate.
A size of 0 or negative is a pathological problem.
C deserves a better readline function.
fgetshas a size to prevent buffer overflow. It's absolutely not a "design flaw". When you callfgetsyou tell the size of the provided buffer andfgetsmakes sure not to write more data to the buffer than the size. So assuming you call the function correct, there won't be any buffer overflow. That's whyfgetsis much better thangets. And better thanscanfwhere many programmers forget to specify a size limit. In (at least) 9 out of 10 casesfgetsis the best way to read input.scanf()is flawed in all kinds of horrid ways.fgets()is well-designed.fgets()is reasonably well designed. It would be better designed if it returned the number of characters it placed in the buffer (either 0 or EOF could indicate EOF). If the input contains null bytes, you can't tell how many characters were read.fgets()works fine on text files and text files do not contain null bytes. However, it would still be better if it reported the number of bytes read.fgets()is not the function to read that type of text file, yet error handling of using the wrong input function is additionally complicated sincefgets()and reading null characters has the extra problem you pointed out.