summaryrefslogtreecommitdiffstats
path: root/src/lib/krb5/krb/x-deltat.y
diff options
context:
space:
mode:
authorEzra Peisach <epeisach@mit.edu>2001-02-16 20:16:02 +0000
committerEzra Peisach <epeisach@mit.edu>2001-02-16 20:16:02 +0000
commita6ae20dc3567a74d027f2b785eb07690d9535317 (patch)
tree33859ff24a48e2dfc99b9f0d1a0846547f8439de /src/lib/krb5/krb/x-deltat.y
parent15f2d27e8bb929bc6efed5bdce6dd10a854a955a (diff)
downloadkrb5-a6ae20dc3567a74d027f2b785eb07690d9535317.tar.gz
krb5-a6ae20dc3567a74d027f2b785eb07690d9535317.tar.xz
krb5-a6ae20dc3567a74d027f2b785eb07690d9535317.zip
* t_deltat.c (main): Test of overflow and underflow of krb5_int32
* x-deltat.y: Test for over/underflow of krb5_int32 for a krb5_deltat. Return EINVAL. [krb5-libs/922] * deltat.c: Regenerated from x-deltat.y * str_conv.c (krb5_string_to_timestamp): Do not accept a time format that only partially matches the input string. [krb5-lib/922] git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@13007 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/krb5/krb/x-deltat.y')
-rw-r--r--src/lib/krb5/krb/x-deltat.y98
1 files changed, 80 insertions, 18 deletions
diff --git a/src/lib/krb5/krb/x-deltat.y b/src/lib/krb5/krb/x-deltat.y
index be53ce3c64..37aa79cbb4 100644
--- a/src/lib/krb5/krb/x-deltat.y
+++ b/src/lib/krb5/krb/x-deltat.y
@@ -42,15 +42,70 @@
#include "k5-int.h"
struct param {
- krb5_deltat delta;
+ krb5_int32 delta;
char *p;
};
#define YYPARSE_PARAM tmv
+#define MAX_TIME KRB5_INT32_MAX
+#define MIN_TIME KRB5_INT32_MIN
+
+#define DAY (24 * 3600)
+#define HOUR 3600
+
+#define MAX_DAY (MAX_TIME / DAY)
+#define MIN_DAY (MIN_TIME / DAY)
+#define MAX_HOUR (MAX_TIME / HOUR)
+#define MIN_HOUR (MIN_TIME / HOUR)
+#define MAX_MIN (MAX_TIME / 60)
+#define MIN_MIN (MIN_TIME / 60)
+
+/* An explanation of the tests being performed.
+ We do not want to overflow a 32 bit integer with out manipulations,
+ even for testing for overflow. Therefore we rely on the following:
+
+ The lex parser will not return a number > MAX_TIME (which is out 32
+ bit limit).
+
+ Therefore, seconds (s) will require
+ MIN_TIME < s < MAX_TIME
+
+ For subsequent tests, the logic is as follows:
+
+ If A < MAX_TIME and B < MAX_TIME
+
+ If we want to test if A+B < MAX_TIME, there are two cases
+ if (A > 0)
+ then A + B < MAX_TIME if B < MAX_TIME - A
+ else A + B < MAX_TIME always.
+
+ if we want to test if MIN_TIME < A + B
+ if A > 0 - then nothing to test
+ otherwise, we test if MIN_TIME - A < B.
+
+ We of course are testing for:
+ MIN_TIME < A + B < MAX_TIME
+*/
+
+
+#define DAY_NOT_OK(d) (d) > MAX_DAY || (d) < MIN_DAY
+#define HOUR_NOT_OK(h) (h) > MAX_HOUR || (h) < MIN_HOUR
+#define MIN_NOT_OK(m) (m) > MAX_MIN || (m) < MIN_MIN
+#define SUM_OK(a, b) (((a) > 0) ? ( (b) <= MAX_TIME - (a)) : (MIN_TIME - (a) <= (b)))
+#define DO_SUM(res, a, b) if (!SUM_OK((a), (b))) YYERROR; \
+ res = (a) + (b)
+
+
+#define OUT_D ((struct param *)tmv)->delta
#define DO(D,H,M,S) \
{ \
- ((struct param *)tmv)->delta = (((D * 24) + H) * 60 + M) * 60 + S; \
+ /* Overflow testing - this does not handle negative values well.. */ \
+ if (DAY_NOT_OK(D) || HOUR_NOT_OK(H) || MIN_NOT_OK(M)) YYERROR; \
+ OUT_D = D * DAY; \
+ DO_SUM(OUT_D, OUT_D, H * HOUR); \
+ DO_SUM(OUT_D, OUT_D, M * 60); \
+ DO_SUM(OUT_D, OUT_D, S); \
}
static int mylex (int *, char **);
@@ -69,7 +124,7 @@ static int yyparse (void *);
%union { int val; }
-%token <val> NUM LONGNUM
+%token <val> NUM LONGNUM OVERFLOW
%token '-' ':' 'd' 'h' 'm' 's' WS
%type <val> num opt_hms opt_ms opt_s wsnum posnum
@@ -78,35 +133,38 @@ static int yyparse (void *);
%%
-start: deltat ;
+start: deltat;
posnum: NUM | LONGNUM ;
num: posnum | '-' posnum { $$ = - $2; } ;
ws: /* nothing */ | WS ;
-wsnum: ws num { $$ = $2; };
+wsnum: ws num { $$ = $2; }
+ | ws OVERFLOW { YYERROR };
deltat:
- wsnum 'd' opt_hms { DO ($1, 0, 0, $3); }
- | wsnum 'h' opt_ms { DO ( 0, $1, 0, $3); }
- | wsnum 'm' opt_s { DO ( 0, 0, $1, $3); }
- | wsnum 's' { DO ( 0, 0, 0, $1); }
- | wsnum '-' NUM ':' NUM ':' NUM { DO ($1, $3, $5, $7); }
- | wsnum ':' NUM ':' NUM { DO ( 0, $1, $3, $5); }
- | wsnum ':' NUM { DO ( 0, $1, $3, 0); }
+ wsnum 'd' opt_hms { DO ($1, 0, 0, $3); }
+ | wsnum 'h' opt_ms { DO ( 0, $1, 0, $3); }
+ | wsnum 'm' opt_s { DO ( 0, 0, $1, $3); }
+ | wsnum 's' { DO ( 0, 0, 0, $1); }
+ | wsnum '-' NUM ':' NUM ':' NUM { DO ($1, $3, $5, $7); }
+ | wsnum ':' NUM ':' NUM { DO ( 0, $1, $3, $5); }
+ | wsnum ':' NUM { DO ( 0, $1, $3, 0); }
;
opt_hms:
opt_ms
- | wsnum 'h' opt_ms { $$ = $1 * 3600 + $3; };
+ | wsnum 'h' opt_ms { if (HOUR_NOT_OK($1)) YYERROR;
+ DO_SUM($$, $1 * 3600, $3); };
opt_ms:
opt_s
- | wsnum 'm' opt_s { $$ = $1 * 60 + $3; };
+ | wsnum 'm' opt_s { if (MIN_NOT_OK($1)) YYERROR;
+ DO_SUM($$, $1 * 60, $3); };
opt_s:
- ws { $$ = 0; }
+ ws { $$ = 0; }
| wsnum 's' ;
%%
static int
-mylex (int *intp, char **pp)
+mylex (krb5_int32 *intp, char **pp)
{
int num, c;
#define P (*pp)
@@ -136,8 +194,12 @@ mylex (int *intp, char **pp)
case '9':
/* XXX assumes ASCII */
num = c - '0';
- while (isdigit (*P)) {
+ while (isdigit ((int) *P)) {
+ if (num > MAX_TIME / 10)
+ return OVERFLOW;
num *= 10;
+ if (num > MAX_TIME - (*P - '0'))
+ return OVERFLOW;
num += *P++ - '0';
}
*intp = num;
@@ -145,7 +207,7 @@ mylex (int *intp, char **pp)
case ' ':
case '\t':
case '\n':
- while (isspace (*P))
+ while (isspace ((int) *P))
P++;
return WS;
default: