Skip to content

Commit

Permalink
alarm() with negative argument makes no sense.
Browse files Browse the repository at this point in the history
Give by default a warning, do not set the alarm, and return undef.

(the signedness problem detected by Coverity, CID 104837)

alarm() takes and returns unsigned int, not signed.

In other words, the C library function alarm() cannot fail, ever.
See for example:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html
http://linux.die.net/man/3/alarm
https://www.freebsd.org/cgi/man.cgi?query=alarm&sektion=3
  • Loading branch information
jhi committed Jun 27, 2015
1 parent 35a328a commit add0dc9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
5 changes: 5 additions & 0 deletions pod/perldiag.pod
Expand Up @@ -7099,6 +7099,11 @@ You likely need to figure out how this multi-byte character got mixed up
with your single-byte locale (or perhaps you thought you had a UTF-8
locale, but Perl disagrees).

=item %s() with negative argument

(S misc) Certain operations make no sense with negative arguments.
Warning is given and the operation is not done.

=item Within []-length '%c' not allowed

(F) The count in the (un)pack template may be replaced by C<[TEMPLATE]>
Expand Down
31 changes: 24 additions & 7 deletions pp_sys.c
Expand Up @@ -4708,13 +4708,30 @@ PP(pp_alarm)
{
#ifdef HAS_ALARM
dSP; dTARGET;
int anum;
anum = POPi;
anum = alarm((unsigned int)anum);
if (anum < 0)
RETPUSHUNDEF;
PUSHi(anum);
RETURN;
/* alarm() takes an unsigned int number of seconds, and return the
* unsigned int number of seconds remaining in the previous alarm
* (alarms don't stack). Therefore negative return values are not
* possible. */
int anum = POPi;
if (anum < 0) {
/* Note that while the C library function alarm() as such has
* no errors defined (or in other words, properly behaving client
* code shouldn't expect any), alarm() being obsoleted by
* setitimer() and often being implemented in terms of
* setitimer(), can fail. */
/* diag_listed_as: %s() with negative argument */
Perl_ck_warner_d(aTHX_ packWARN(WARN_MISC),
"alarm() with negative argument");
SETERRNO(EINVAL, LIB_INVARG);
RETPUSHUNDEF;
}
else {
unsigned int retval = alarm(anum);
if ((int)retval < 0) /* Strictly speaking "cannot happen". */
RETPUSHUNDEF;
PUSHu(retval);
RETURN;
}
#else
DIE(aTHX_ PL_no_func, "alarm");
#endif
Expand Down
9 changes: 9 additions & 0 deletions t/lib/warnings/pp_sys
Expand Up @@ -921,3 +921,12 @@ gmtime(NaN) too large at - line 6.
gmtime(NaN) failed at - line 6.
localtime(NaN) too large at - line 7.
localtime(NaN) failed at - line 7.

########
# pp_sys.c [pp_alarm]
alarm(-1);
no warnings "misc";
alarm(-1);

EXPECT
alarm() with negative argument at - line 2.

0 comments on commit add0dc9

Please sign in to comment.