Merge pull request #1442 from xexyl/gets-thanks
This commit is contained in:
1 file changed
+64
-112
+64
-112
@@ -80,10 +80,28 @@ $ warning: this program uses gets(), which is unsafe.
|
||||
|
||||
whereas without the warning it's much easier to see that it's a prompt.
|
||||
|
||||
Another great example is:
|
||||
|
||||
```sh
|
||||
$ cd 1990/cmills
|
||||
$ ./cmills
|
||||
Shuffle...
|
||||
warning: this program uses gets(), which is unsafe.
|
||||
Total $1000. Wager?
|
||||
```
|
||||
|
||||
In some entries this change is not possible, in one-liners it might make them
|
||||
too long (though it's also been possible to do it in some cases) and in some
|
||||
entries it's more complicated than others because of the annoying fact that for
|
||||
'"compatibility" reasons' `fgets()` retains the newline and `gets()` does not.
|
||||
As the v7 man page used to say:
|
||||
|
||||
```
|
||||
BUGS
|
||||
|
||||
The fgets(3) function retains the newline while gets(3) does not, all in the
|
||||
name of backward compatibility.
|
||||
```
|
||||
|
||||
Some entries like [1992/adrian](1992/adrian/README.md) were more complicated in
|
||||
other ways due to the code generating other output and because of how it works
|
||||
@@ -94,6 +112,9 @@ fixes in that entry.
|
||||
In any case some of the entries have been updated this way for the reasons
|
||||
described above and in the [FAQ](/faq.md).
|
||||
|
||||
Where possible `gets` has been redefined to be `fgets` with the appropriate arg.
|
||||
This is not always possible but if often is.
|
||||
|
||||
See also [bugs.md](/bugs.md) for a further discussion on the matter.
|
||||
|
||||
|
||||
@@ -125,7 +146,7 @@ they were not fixed as the problems were documented by the author or us.
|
||||
|
||||
Of course it can be argued that by fixing these things it makes it more user
|
||||
friendly for modern enjoyment but even so it's very often the wrong way to go
|
||||
about it. If the author does not mention it t hen it can be considered a bug
|
||||
about it. If the author does not mention it then it can be considered a bug
|
||||
that can be fixed.
|
||||
|
||||
See the [bugs.md](/bugs.md) for more information regarding this situation and
|
||||
@@ -408,9 +429,7 @@ commented out.
|
||||
|
||||
## [1986/hague](1986/hague/hague.c) ([README.md](1986/hague/README.md]))
|
||||
|
||||
Cody made this use `fgets()` to avoid alarming and annoying messages about
|
||||
`gets()` being unsafe, sometimes interspersed with the output of the program.
|
||||
For more details about that see the [FAQ](/faq.md).
|
||||
Cody made this use `fgets()`.
|
||||
|
||||
|
||||
## [1986/holloway](1986/holloway/holloway.c) ([README.md](1986/holloway/README.md]))
|
||||
@@ -599,15 +618,7 @@ size constraints of the contest).
|
||||
|
||||
## [1987/wall](1987/wall/wall.c) ([README.md](1987/wall/README.md]))
|
||||
|
||||
Cody made this safer by using `fgets()` instead of `gets()`. This prevents an
|
||||
annoying and potentially alarming warning at compiling, linking or runtime.
|
||||
Though this could be partly remedied through redirecting `stderr` to `/dev/null`
|
||||
this would not truly resolve the problem either and in order to avoid the
|
||||
warning one would have to always redirect `stderr` to `/dev/null`.
|
||||
|
||||
Later Cody improved upon the `gets()`/`fgets()` change to make it more like the
|
||||
original by redefining `gets()` to use `fgets()` (with the correct args) so that
|
||||
the code can refer to `gets()` instead.
|
||||
Cody made this use `fgets(3)`.
|
||||
|
||||
|
||||
## [1987/westley](1987/westley/westley.c) ([README.md](1987/westley/README.md]))
|
||||
@@ -738,11 +749,7 @@ to itself and `pain()` does now.
|
||||
|
||||
## [1988/reddy](1988/reddy/reddy.c) ([README.md](1988/reddy/README.md))
|
||||
|
||||
Cody made this use `fgets()` to prevent annoying warnings during compiling,
|
||||
linking and runtime, the latter of which being the most annoying.
|
||||
|
||||
Cody also restored the name of the winner in the README.md file that was missing
|
||||
by some crazy chance.
|
||||
Cody made this use `fgets(3)`.
|
||||
|
||||
|
||||
## [1988/spinellis](1988/spinellis/spinellis.c) ([README.md](1988/spinellis/README.md]))
|
||||
@@ -981,17 +988,7 @@ judges was retained.
|
||||
Yusuke got this to work in modern systems (it previously resulted in a bus
|
||||
error).
|
||||
|
||||
To prevent alarming warnings at linking or runtime Cody made the entry use
|
||||
`fgets()` rather than `gets()`. He notes that another option would have been to
|
||||
redirect `stderr` to `/dev/null` but he did not think of that at the time.
|
||||
|
||||
Cody later improved upon the `gets()`/`fgets()` fix to make it more like the
|
||||
original where the code can refer to `gets()` in the way it originally did. This
|
||||
was done through a macro to redefine `gets`.
|
||||
|
||||
BTW: Cody asks the following question: if the compiler compiles, the linker
|
||||
links and the user executes does that make the compiler the jury, the linker the
|
||||
judge and user the executioner? :-)
|
||||
Cody made this use `fgets(3)`.
|
||||
|
||||
|
||||
## [1990/dds](1990/dds/dds.c) ([README.md](1990/dds/README.md]))
|
||||
@@ -1008,16 +1005,7 @@ Cody fixed another compiler error by removing the erroneous prototype to
|
||||
`fopen()`. Cody also changed a `char *` used for file I/O to be a proper `FILE
|
||||
*` and fixed a typo in [LANDER.BAS](1990/dds/LANDER.BAS).
|
||||
|
||||
Cody also made this use `fgets()` instead of `gets()` to make it safer and to
|
||||
prevent an annoying and potentially alarming warning at compiling and/or linking
|
||||
and/or runtime, the latter of which is unfortunately interspersed with the
|
||||
output of the program.
|
||||
|
||||
Later Cody improved the `gets()`/`fgets()` fix by redefining `gets()` to use
|
||||
`fgets()`. Notice that the original entry used `fgets()` in one case as it has
|
||||
to read from another file and in this place nothing was changed.
|
||||
|
||||
With these improvements the entry looks much more like the original!
|
||||
Cody also made this use `fgets(3)`.
|
||||
|
||||
|
||||
## [1990/dg](1990/dg/dg.c) ([README.md](1990/dg/README.md]))
|
||||
@@ -1074,22 +1062,13 @@ suggested `-trigraphs`. Both work but we used Yusuke's idea.
|
||||
## [1990/tbr](1990/tbr/tbr.c) ([README.md](1990/tbr/README.md]))
|
||||
|
||||
Cody fixed this to work with modern compilers; `exit(3)` returns void but the
|
||||
function was used in a binary expression so this wouldn't even compile. Cody
|
||||
also changed the code to use `fgets()` instead of `gets()` so one would not get
|
||||
a warning about the use of `gets()` at linking time or execution, the latter of
|
||||
function was used in a binary expression so this wouldn't even compile.
|
||||
|
||||
Cody also changed the code to use `fgets()` instead of `gets()` so one would not get
|
||||
a warning about the use of `gets(3)` at linking time or execution, the latter of
|
||||
which was causing confusing output due to the warning being interspersed with
|
||||
the program's interactive output.
|
||||
|
||||
Cody later improved his fix so that it looks more like the original. A problem
|
||||
that usually occurs with `gets()` to `fgets()` is for 'backwards compatibility'
|
||||
(so the man page once said) `fgets()` retains the newline and `gets()` does not.
|
||||
In this program if one does not remove the newline it breaks the program. This
|
||||
usually requires that one check that `fgets()` does not return NULL but with
|
||||
some experimenting this proved to seem to not be a problem here so by adding a
|
||||
couple macros that redefine `exit()` and `gets()` a whole binary expression
|
||||
could be removed (thus removing an extra `exit()` call) and it now almost looks
|
||||
like the same as the original.
|
||||
|
||||
Additionally, Cody fixed the shortened version provided by the author in the
|
||||
same way as the original entry, first the compile fix and then later on making
|
||||
it look more like the original by redefining `exit` and also redefining `gets()`
|
||||
@@ -1121,11 +1100,10 @@ if (a[1]==NULL||a[2]==NULL||a[3]==NULL||a[4]==NULL||a[5]==NULL) return 1;
|
||||
|
||||
be changed to just test the value of `A` when `a` is argv and `A` is argc?
|
||||
|
||||
Cody also changed the code to use `fgets(3)`.
|
||||
|
||||
Finally Cody changed this program to use `fgets()` not `gets()` to make it safer
|
||||
and to prevent a warning about `gets()` at linking or runtime. Since this
|
||||
program is so incredible the extra fixes were deemed worth having and this is why
|
||||
it was done.
|
||||
Since this program is so incredible the extra fixes were deemed worth having and
|
||||
this is why it was done.
|
||||
|
||||
Cody later disabled a warning in the Makefile that proved to be a problem only
|
||||
with clang in linux but which was defaulting to an error. This way was the
|
||||
@@ -1256,8 +1234,8 @@ string. Thus the end of the string actually looks like:
|
||||
!.Xop.fssps!.Xop.sfuvso.uzqf!.Xop.jnqmjdju.gvodujpo.efdmbsbujpo!b/d
|
||||
```
|
||||
|
||||
But then there is the matter of getting the C to use `fgets()`. As can be seen
|
||||
above it's not as simple as changing `gets()` to `fgets()`. This was more magic
|
||||
But then there is the matter of getting the C to use `fgets(3)`. As can be seen
|
||||
above it's not as simple as changing `gets(3)` to `fgets(3)`. This was more magic
|
||||
characters that had to be updated and some added. The C code:
|
||||
|
||||
```c
|
||||
@@ -1327,8 +1305,8 @@ It is hoped that this is the last time the string has to be updated to work with
|
||||
all versions of clang but if not the above is how it works.
|
||||
|
||||
With these changes in place it will compile and work with both gcc and clang and
|
||||
the C code generated will use `fgets()`, not `gets()`, therefore removing the
|
||||
annoying warnings. Note that the array passed to `fgets()` is an int but that
|
||||
the C code generated will use `fgets(3)`, not `gets(3)`, therefore removing the
|
||||
annoying warnings. Note that the array passed to `fgets(3)` is an int but that
|
||||
was the same for `gets()` and is not necessary to update to a `char[]`.
|
||||
|
||||
The key to the string is that it rotates the character by `+1`. This was not
|
||||
@@ -1439,33 +1417,27 @@ Cody also restored a slightly more obscure line of code that had been changed:
|
||||
|
||||
though it's questionable how much more (if at all) obscure that is :-)
|
||||
|
||||
Cody also changed the location that it used `gets()` to be `fgets()` instead to
|
||||
make it safer and to prevent annoying warnings during compiling, linking or
|
||||
runtime (interspersed with the program's output). This was complicated because
|
||||
of how the other source files are generated (as above); simply changing the code
|
||||
could cause invalid output in the program which made other files fail to compile
|
||||
(for this example specifically, see below).
|
||||
Cody also changed the location that it used `gets()` to be `fgets(3)`.
|
||||
This was complicated because of how the other source files are generated (as
|
||||
above); simply changing the code could cause invalid output in the program which
|
||||
made other files fail to compile (for this example specifically, see below).
|
||||
|
||||
One might think that simply changing the `gets()` to `fgets()` (with `stdin`)
|
||||
would work but it did not because `fgets()` stores the newline and `gets()` does
|
||||
One might think that simply changing the `gets(3)` to `fgets(3)` (with `stdin`)
|
||||
would work but it did not because `fgets(3)` stores the newline and `gets(3)` does
|
||||
not. That is well known but this code was relying on not having this newline in
|
||||
a different way (see also above).
|
||||
|
||||
With `fgets()` the code `if(A(Y)) puts(Y);` ended up printing an extra line
|
||||
With `fgets(3)` the code `if(A(Y)) puts(Y);` ended up printing an extra line
|
||||
which made the generation of some files (like `adhead.c`) fail to compile. Why?
|
||||
There was a blank line after a `\` at the end of the first line of a _macro
|
||||
definition_! Thus the code now first trims off the last character of the buffer
|
||||
read to get the same correct functionality but in a safe and non obnoxious way.
|
||||
|
||||
Later Cody improved the change to `fgets()` to make it slightly more like the
|
||||
original. This still requires the additional stripping of the newline inside the
|
||||
loop but now it uses what looks like before, just a call to `gets()`.
|
||||
|
||||
But the improvement so that it uses `gets()` could not be changed to have the
|
||||
macro do the removal of the extra line (as in with a comma operator or a `&&`)
|
||||
as this, as might be expected from the above, caused compilation errors with
|
||||
another generated file (`adwc.c`)! Thus after the `gets()` call in the line that
|
||||
looks like:
|
||||
In this case the macro for `gets` could not be changed to have the macro do the
|
||||
removal of the extra line (as in with a comma operator or a `&&`) as this, as
|
||||
might be expected from the above, caused compilation errors with another
|
||||
generated file (`adwc.c`)! Thus after the `gets(3)` call in the line that looks
|
||||
like:
|
||||
|
||||
```c
|
||||
while( gets(Y) ){ Y[strlen(Y)-1]='\0'; if(A(Y)) puts(Y); }
|
||||
@@ -1522,18 +1494,18 @@ commands that we suggested and some additional ones that provide for some fun.
|
||||
Cody fixed a crash that prevented this entry from working in some cases in some
|
||||
systems (like macOS) by disabling the optimiser in the Makefile.
|
||||
|
||||
Cody also changed the buffer size in such a way that `gets()` should be safe
|
||||
Cody also changed the buffer size in such a way that `gets(3)` should be safe
|
||||
(theoretically) as it comes from the command line (though it can also read input
|
||||
from stdin after starting the program). Ideally `fgets()` would be used but this
|
||||
from stdin after starting the program). Ideally `fgets(3)` would be used but this
|
||||
is a more problematic. Previously it had a buffer size of 256 which could
|
||||
easily overflow. In this entry `gets()` is used in a more complicated way:
|
||||
easily overflow. In this entry `gets(3)` is used in a more complicated way:
|
||||
first `m` is set to `*++p` in a for loop where `p` is argv. Later `m` is set to
|
||||
point to `h` which was of size 256. `gets()` is called as `m = gets(m)`) but
|
||||
trying to change it to use `fgets()` proved more a problem. Since the input must
|
||||
point to `h` which was of size 256. `gets(3)` is called as `m = gets(m)`) but
|
||||
trying to change it to use `fgets(3)` proved more a problem. Since the input must
|
||||
come from the command line Cody changed the buffer size to `ARG_MAX+1` which
|
||||
should be enough (again theoretically) especially since the command expects
|
||||
redirecting a dictionary file as part of the command line. This also makes it
|
||||
possible for longer strings to be read (in case the `gets()` was not used in a
|
||||
possible for longer strings to be read (in case the `gets(3)` was not used in a
|
||||
loop).
|
||||
|
||||
Cody also added the [mkdict.sh](1992/gson/mkdict.sh) script that the author
|
||||
@@ -1578,17 +1550,9 @@ Judges' remarks in the README.md file) this will not work with clang.
|
||||
Cody also provided the `runme.sh` script to demonstrate it as using make was
|
||||
problematic.
|
||||
|
||||
Cody made it use `fgets()` instead of `gets()` to prevent annoying warnings
|
||||
getting in the way (in linux linking in a binary with `gets()` produces a
|
||||
warning that might get in the way with this entry and in macOS at runtime it
|
||||
prints a warning which often is interspersed with the output of the program
|
||||
which can be confusing).
|
||||
Cody made it use `fgets()` instead of `gets()`.
|
||||
|
||||
Cody later improved the `fgets()` change to look more like the original i.e. it
|
||||
now uses a redefined `gets()`. This did require modifying the line number with
|
||||
`#line 1` under the macro `gets()`.
|
||||
|
||||
Still this cannot work with clang due to different compiler messages. See
|
||||
NOTE: this entry cannot work with clang due to different compiler messages. See
|
||||
[bugs.md](/bugs.md) for details.
|
||||
|
||||
|
||||
@@ -1718,12 +1682,7 @@ compile time. See the README.md for details.
|
||||
|
||||
## [1993/schnitzi](1993/schnitzi/schnitzi.c) ([README.md](1993/schnitzi/README.md]))
|
||||
|
||||
Cody made this use `fgets()` not `gets()` to make it safer and to prevent an
|
||||
annoying warning with compiling and/or linking and/or runtime, the latter of
|
||||
which is unfortunately interspersed with the output of the program itself.
|
||||
|
||||
Cody later improved the fix to use `gets()` via a macro so that it looks like
|
||||
the original code.
|
||||
Cody made this use `fgets(3)` not `gets(3)`.
|
||||
|
||||
|
||||
## [1993/vanb](1993/vanb/vanb.c) ([README.md](1993/vanb/README.md]))
|
||||
@@ -1808,12 +1767,10 @@ Cody also fixed it for clang under linux which objected to incompatible pointer
|
||||
type (because `time(2)` takes a `time_t *` which in some systems is a `long *`
|
||||
but what was being passed to it is an `int`).
|
||||
|
||||
Cody also changed the entry to use `fgets()` instead of `gets()` to make it safe
|
||||
for lines greater than 231 in length and to prevent a warning at linking or at
|
||||
runtime, the latter of which can be interspersed with output of the program.
|
||||
Note that this now prints a newline after the output but this seems like a
|
||||
worthy compromise for preventing the interspersed output in macOS and at the
|
||||
same time it's safer (fixing it to not have the extra newline is more
|
||||
Cody also changed the entry to use `fgets(3)` instead of `gets(3)`. This one has
|
||||
a minor annoyance in that it now prints a newline after the output but this
|
||||
seems like a worthy compromise for preventing the interspersed output in macOS
|
||||
and at the same time it's safer (fixing it to not have the extra newline is more
|
||||
problematic than it's worth and in macOS another line of output would be shown
|
||||
without the change anyway and the difference is that now it's just a blank line
|
||||
rather than an annoying warning).
|
||||
@@ -2257,14 +2214,9 @@ commands that we recommended.
|
||||
|
||||
## [2000/anderson](2000/anderson/anderson.c) ([README.md](2000/anderson/README.md]))
|
||||
|
||||
Cody changed this entry to use `fgets()` instead of `gets()` to make it safer
|
||||
and to prevent annoying warnings from showing up at compiling, linking and/or
|
||||
runtime, the latter interspersed with the output of the program. This involved
|
||||
Cody changed this entry to use `fgets(3)` instead of `gets(3)`. This involved
|
||||
changing the `K` arg to `gets(3)` to `&K` in `fgets(3)`.
|
||||
|
||||
Cody later improved the fix to use `gets()` by redefining `gets()` so that the
|
||||
code looks like before.
|
||||
|
||||
Cody also added the [try.sh](2000/anderson/try.sh) script.
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user