summaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/lib/krb5/krb/ChangeLog12
-rw-r--r--src/lib/krb5/krb/deltat.c258
-rw-r--r--src/lib/krb5/krb/str_conv.c5
-rw-r--r--src/lib/krb5/krb/t_deltat.c53
-rw-r--r--src/lib/krb5/krb/x-deltat.y98
5 files changed, 308 insertions, 118 deletions
diff --git a/src/lib/krb5/krb/ChangeLog b/src/lib/krb5/krb/ChangeLog
index 8c6f20a8c..d22f20790 100644
--- a/src/lib/krb5/krb/ChangeLog
+++ b/src/lib/krb5/krb/ChangeLog
@@ -1,3 +1,15 @@
+2001-02-15 Ezra Peisach <epeisach@mit.edu>
+
+ * 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]
+
2001-01-30 Tom Yu <tlyu@mit.edu>
* preauth.c (krb5_obtain_padata): Don't dereference a NULL pointer
diff --git a/src/lib/krb5/krb/deltat.c b/src/lib/krb5/krb/deltat.c
index dbf990092..f2431e184 100644
--- a/src/lib/krb5/krb/deltat.c
+++ b/src/lib/krb5/krb/deltat.c
@@ -1,38 +1,86 @@
-/* A Bison parser, made from ../../../../asrc/lib/krb5/krb/x-deltat.y
- by GNU Bison version 1.27
- */
+/* A Bison parser, made from ../../../../src/lib/krb5/krb/x-deltat.y
+ by GNU Bison version 1.28 */
#define YYBISON 1 /* Identify Bison output. */
#define NUM 257
#define LONGNUM 258
-#define WS 259
+#define OVERFLOW 259
+#define WS 260
-#line 38 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 38 "../../../../src/lib/krb5/krb/x-deltat.y"
#include <ctype.h>
#include <errno.h>
#include "k5-int.h"
-#if 0
-#define NBITS(TYPE) (8*sizeof(TYPE))
-#define LOG10_2 0.30103
-#define LOG10_MAX(TYPE) (LOG10_2 * NBITS(TYPE))
-#define BUFFERSIZE(TYPE) (1 /* \0 */ + (int) (1 + LOG10_MAX(TYPE)))
-#endif
-
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 **);
@@ -46,7 +94,7 @@ static int mylex (int *, char **);
static int yyparse (void *);
-#line 77 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 125 "../../../../src/lib/krb5/krb/x-deltat.y"
typedef union { int val; } YYSTYPE;
#include <stdio.h>
@@ -58,25 +106,25 @@ typedef union { int val; } YYSTYPE;
-#define YYFINAL 41
+#define YYFINAL 42
#define YYFLAG -32768
-#define YYNTBASE 12
+#define YYNTBASE 13
-#define YYTRANSLATE(x) ((unsigned)(x) <= 259 ? yytranslate[x] : 21)
+#define YYTRANSLATE(x) ((unsigned)(x) <= 260 ? yytranslate[x] : 22)
static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 5, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 6, 2, 2,
+ 2, 2, 2, 2, 6, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 2, 2, 2, 8, 2, 2, 2, 2, 9, 2,
- 2, 2, 2, 2, 10, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 8,
+ 2, 2, 2, 9, 2, 2, 2, 2, 10, 2,
+ 2, 2, 2, 2, 11, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -90,33 +138,33 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 3, 4, 11
+ 2, 2, 2, 2, 2, 1, 3, 4, 5, 12
};
#if YYDEBUG != 0
static const short yyprhs[] = { 0,
- 0, 2, 4, 6, 8, 11, 12, 14, 17, 21,
- 25, 29, 32, 40, 46, 50, 52, 56, 58, 62,
- 64
+ 0, 2, 4, 6, 8, 11, 12, 14, 17, 20,
+ 24, 28, 32, 35, 43, 49, 53, 55, 59, 61,
+ 65, 67
};
-static const short yyrhs[] = { 17,
- 0, 3, 0, 4, 0, 13, 0, 5, 13, 0,
- 0, 11, 0, 15, 14, 0, 16, 7, 18, 0,
- 16, 8, 19, 0, 16, 9, 20, 0, 16, 10,
- 0, 16, 5, 3, 6, 3, 6, 3, 0, 16,
- 6, 3, 6, 3, 0, 16, 6, 3, 0, 19,
- 0, 16, 8, 19, 0, 20, 0, 16, 9, 20,
- 0, 15, 0, 16, 10, 0
+static const short yyrhs[] = { 18,
+ 0, 3, 0, 4, 0, 14, 0, 6, 14, 0,
+ 0, 12, 0, 16, 15, 0, 16, 5, 0, 17,
+ 8, 19, 0, 17, 9, 20, 0, 17, 10, 21,
+ 0, 17, 11, 0, 17, 6, 3, 7, 3, 7,
+ 3, 0, 17, 7, 3, 7, 3, 0, 17, 7,
+ 3, 0, 20, 0, 17, 9, 20, 0, 21, 0,
+ 17, 10, 21, 0, 16, 0, 17, 11, 0
};
#endif
#if YYDEBUG != 0
static const short yyrline[] = { 0,
- 88, 89, 89, 90, 90, 91, 91, 92, 93, 95,
- 96, 97, 98, 99, 100, 103, 105, 106, 108, 109,
- 111
+ 136, 137, 137, 138, 138, 139, 139, 140, 141, 142,
+ 144, 145, 146, 147, 148, 149, 152, 154, 156, 158,
+ 160, 162
};
#endif
@@ -124,69 +172,69 @@ static const short yyrline[] = { 0,
#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
static const char * const yytname[] = { "$","error","$undefined.","NUM","LONGNUM",
-"'-'","':'","'d'","'h'","'m'","'s'","WS","start","posnum","num","ws","wsnum",
-"deltat","opt_hms","opt_ms","opt_s", NULL
+"OVERFLOW","'-'","':'","'d'","'h'","'m'","'s'","WS","start","posnum","num","ws",
+"wsnum","deltat","opt_hms","opt_ms","opt_s", NULL
};
#endif
static const short yyr1[] = { 0,
- 12, 13, 13, 14, 14, 15, 15, 16, 17, 17,
- 17, 17, 17, 17, 17, 18, 18, 19, 19, 20,
- 20
+ 13, 14, 14, 15, 15, 16, 16, 17, 17, 18,
+ 18, 18, 18, 18, 18, 18, 19, 19, 20, 20,
+ 21, 21
};
static const short yyr2[] = { 0,
- 1, 1, 1, 1, 2, 0, 1, 2, 3, 3,
- 3, 2, 7, 5, 3, 1, 3, 1, 3, 1,
- 2
+ 1, 1, 1, 1, 2, 0, 1, 2, 2, 3,
+ 3, 3, 2, 7, 5, 3, 1, 3, 1, 3,
+ 1, 2
};
static const short yydefact[] = { 6,
- 7, 0, 0, 1, 2, 3, 0, 4, 8, 0,
- 0, 6, 6, 6, 12, 5, 0, 15, 20, 0,
- 9, 16, 18, 0, 10, 0, 11, 0, 0, 6,
- 6, 21, 0, 14, 17, 19, 0, 13, 0, 0,
- 0
+ 7, 0, 0, 1, 2, 3, 9, 0, 4, 8,
+ 0, 0, 6, 6, 6, 13, 5, 0, 16, 21,
+ 0, 10, 17, 19, 0, 11, 0, 12, 0, 0,
+ 6, 6, 22, 0, 15, 18, 20, 0, 14, 0,
+ 0, 0
};
-static const short yydefgoto[] = { 39,
- 8, 9, 19, 24, 4, 21, 22, 23
+static const short yydefgoto[] = { 40,
+ 9, 10, 20, 25, 4, 22, 23, 24
};
-static const short yypact[] = { -9,
--32768, 12, -1,-32768,-32768,-32768, 7,-32768,-32768, 10,
- 16, -9, -9, -9,-32768,-32768, 20, 21, 12, 13,
--32768,-32768,-32768, 15,-32768, 18,-32768, 26, 27, -9,
- -9,-32768, 28,-32768,-32768,-32768, 29,-32768, 33, 35,
--32768
+static const short yypact[] = { -10,
+-32768, 18, -2,-32768,-32768,-32768,-32768, 13,-32768,-32768,
+ 11, 16, -10, -10, -10,-32768,-32768, 20, 21, 18,
+ 1,-32768,-32768,-32768, 15,-32768, 19,-32768, 26, 28,
+ -10, -10,-32768, 27,-32768,-32768,-32768, 30,-32768, 35,
+ 36,-32768
};
static const short yypgoto[] = {-32768,
- 30,-32768, 36, 0,-32768,-32768, -12, -11
+ 29,-32768, 38, 0,-32768,-32768, -13, -12
};
-#define YYLAST 37
+#define YYLAST 38
static const short yytable[] = { 3,
- 25, 1, 27, 10, 11, 12, 13, 14, 15, 5,
- 6, 20, 17, 26, 5, 6, 7, 35, 18, 36,
- 30, 31, 32, 31, 32, 28, 29, 32, 33, 34,
- 26, 38, 40, 37, 41, 2, 16
+ 26, 1, 28, 11, 12, 13, 14, 15, 16, 31,
+ 32, 33, 21, 18, 27, 5, 6, 36, 19, 37,
+ 5, 6, 7, 8, 32, 33, 29, 30, 34, 33,
+ 35, 27, 39, 38, 41, 42, 17, 2
};
static const short yycheck[] = { 0,
- 13, 11, 14, 5, 6, 7, 8, 9, 10, 3,
- 4, 12, 3, 14, 3, 4, 5, 30, 3, 31,
- 8, 9, 10, 9, 10, 6, 6, 10, 3, 3,
- 31, 3, 0, 6, 0, 0, 7
+ 14, 12, 15, 6, 7, 8, 9, 10, 11, 9,
+ 10, 11, 13, 3, 15, 3, 4, 31, 3, 32,
+ 3, 4, 5, 6, 10, 11, 7, 7, 3, 11,
+ 3, 32, 3, 7, 0, 0, 8, 0
};
#define YYPURE 1
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/mit/gnu/share/bison.simple"
-/* This file comes from bison-1.27. */
+#line 3 "/tmp/bison/share/bison.simple"
+/* This file comes from bison-1.28. */
/* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
@@ -399,7 +447,7 @@ __yy_memcpy (char *to, char *from, unsigned int count)
#endif
#endif
-#line 216 "/mit/gnu/share/bison.simple"
+#line 217 "/tmp/bison/share/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
@@ -728,56 +776,62 @@ yyreduce:
switch (yyn) {
case 5:
-#line 90 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 138 "../../../../src/lib/krb5/krb/x-deltat.y"
{ yyval.val = - yyvsp[0].val; ;
break;}
case 8:
-#line 92 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 140 "../../../../src/lib/krb5/krb/x-deltat.y"
{ yyval.val = yyvsp[0].val; ;
break;}
case 9:
-#line 94 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO (yyvsp[-2].val, 0, 0, yyvsp[0].val); ;
+#line 141 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ YYERROR ;
break;}
case 10:
-#line 95 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO ( 0, yyvsp[-2].val, 0, yyvsp[0].val); ;
+#line 143 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO (yyvsp[-2].val, 0, 0, yyvsp[0].val); ;
break;}
case 11:
-#line 96 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO ( 0, 0, yyvsp[-2].val, yyvsp[0].val); ;
+#line 144 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO ( 0, yyvsp[-2].val, 0, yyvsp[0].val); ;
break;}
case 12:
-#line 97 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO ( 0, 0, 0, yyvsp[-1].val); ;
+#line 145 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO ( 0, 0, yyvsp[-2].val, yyvsp[0].val); ;
break;}
case 13:
-#line 98 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO (yyvsp[-6].val, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;
+#line 146 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO ( 0, 0, 0, yyvsp[-1].val); ;
break;}
case 14:
-#line 99 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO ( 0, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;
+#line 147 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO (yyvsp[-6].val, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;
break;}
case 15:
-#line 100 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ DO ( 0, yyvsp[-2].val, yyvsp[0].val, 0); ;
+#line 148 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO ( 0, yyvsp[-4].val, yyvsp[-2].val, yyvsp[0].val); ;
break;}
-case 17:
-#line 105 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ yyval.val = yyvsp[-2].val * 3600 + yyvsp[0].val; ;
+case 16:
+#line 149 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ DO ( 0, yyvsp[-2].val, yyvsp[0].val, 0); ;
break;}
-case 19:
-#line 108 "../../../../asrc/lib/krb5/krb/x-deltat.y"
-{ yyval.val = yyvsp[-2].val * 60 + yyvsp[0].val; ;
+case 18:
+#line 154 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ if (HOUR_NOT_OK(yyvsp[-2].val)) YYERROR;
+ DO_SUM(yyval.val, yyvsp[-2].val * 3600, yyvsp[0].val); ;
break;}
case 20:
-#line 110 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 158 "../../../../src/lib/krb5/krb/x-deltat.y"
+{ if (MIN_NOT_OK(yyvsp[-2].val)) YYERROR;
+ DO_SUM(yyval.val, yyvsp[-2].val * 60, yyvsp[0].val); ;
+ break;}
+case 21:
+#line 161 "../../../../src/lib/krb5/krb/x-deltat.y"
{ yyval.val = 0; ;
break;}
}
/* the action file gets copied in in place of this dollarsign */
-#line 542 "/mit/gnu/share/bison.simple"
+#line 543 "/tmp/bison/share/bison.simple"
yyvsp -= yylen;
yyssp -= yylen;
@@ -997,11 +1051,11 @@ yyerrhandle:
}
return 1;
}
-#line 113 "../../../../asrc/lib/krb5/krb/x-deltat.y"
+#line 164 "../../../../src/lib/krb5/krb/x-deltat.y"
static int
-mylex (int *intp, char **pp)
+mylex (krb5_int32 *intp, char **pp)
{
int num, c;
#define P (*pp)
@@ -1031,8 +1085,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;
@@ -1040,7 +1098,7 @@ mylex (int *intp, char **pp)
case ' ':
case '\t':
case '\n':
- while (isspace (*P))
+ while (isspace ((int) *P))
P++;
return WS;
default:
diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c
index e795bd253..70fac19fa 100644
--- a/src/lib/krb5/krb/str_conv.c
+++ b/src/lib/krb5/krb/str_conv.c
@@ -47,6 +47,7 @@
*/
#include "k5-int.h"
+#include <ctype.h>
/* Salt type conversions */
@@ -184,6 +185,10 @@ krb5_string_to_timestamp(string, timestampp)
memcpy(&timebuf, localtime(&now), sizeof(timebuf));
if ((s = strptime(string, atime_format_table[i], &timebuf))
&& (s != string)) {
+ /* See if at end of buffer - otherwise partial processing */
+ while(*s != 0 && isspace((int) *s)) s++;
+ if (*s != 0)
+ continue;
if (timebuf.tm_year <= 0)
continue; /* clearly confused */
ret_time = mktime(&timebuf);
diff --git a/src/lib/krb5/krb/t_deltat.c b/src/lib/krb5/krb/t_deltat.c
index 3e376b10a..ebf1a64d2 100644
--- a/src/lib/krb5/krb/t_deltat.c
+++ b/src/lib/krb5/krb/t_deltat.c
@@ -72,6 +72,59 @@ main ()
/* misc */
BAD ("42"),
BAD ("1-2"),
+ /* Test overflow limitations */
+ GOOD ("2147483647s", 2147483647),
+ BAD ("2147483648s"),
+ GOOD ("24855d", 24855 * DAY),
+ BAD ("24856d"),
+ BAD ("24855d 100000000h"),
+ GOOD ("24855d 3h", 24855 * DAY + 3 * HOUR),
+ BAD ("24855d 4h"),
+ GOOD ("24855d 11647s", 24855 * DAY + 11647),
+ BAD ("24855d 11648s"),
+ GOOD ("24855d 194m 7s", 24855 * DAY + 194 * MIN + 7),
+ BAD ("24855d 194m 8s"),
+ BAD ("24855d 195m"),
+ BAD ("24855d 19500000000m"),
+ GOOD ("24855d 3h 14m 7s", 24855 * DAY + 3 * HOUR + 14 * MIN + 7),
+ BAD ("24855d 3h 14m 8s"),
+ GOOD ("596523h", 596523 * HOUR),
+ BAD ("596524h"),
+ GOOD ("596523h 847s", 596523 * HOUR + 847),
+ BAD ("596523h 848s"),
+ GOOD ("596523h 14m 7s", 596523 * HOUR + 14 * MIN + 7),
+ BAD ("596523h 14m 8s"),
+ GOOD ("35791394m", 35791394 * MIN),
+ GOOD ("35791394m7s", 35791394 * MIN + 7),
+ BAD ("35791394m8s"),
+ /* Test underflow */
+ GOOD ("-2147483647s", -2147483647),
+ /* This should be valid, but isn't */
+ /*BAD ("-2147483648s"),*/
+ GOOD ("-24855d", -24855 * DAY),
+ BAD ("-24856d"),
+ BAD ("-24855d -100000000h"),
+ GOOD ("-24855d -3h", -24855 * DAY - 3 * HOUR),
+ BAD ("-24855d -4h"),
+ GOOD ("-24855d -11647s", -24855 * DAY - 11647),
+ BAD ("-24855d -11649s"),
+ GOOD ("-24855d -194m -7s", -24855 * DAY - 194 * MIN - 7),
+ BAD ("-24855d -194m -9s"),
+ BAD ("-24855d -195m"),
+ BAD ("-24855d -19500000000m"),
+ GOOD ("-24855d -3h -14m -7s", -24855 * DAY - 3 * HOUR - 14 * MIN - 7),
+ BAD ("-24855d -3h -14m -9s"),
+ GOOD ("-596523h", -596523 * HOUR),
+ BAD ("-596524h"),
+ GOOD ("-596523h -847s", -596523 * HOUR - 847),
+ GOOD ("-596523h -848s", -596523 * HOUR - 848),
+ BAD ("-596523h -849s"),
+ GOOD ("-596523h -14m -8s", -596523 * HOUR - 14 * MIN - 8),
+ BAD ("-596523h -14m -9s"),
+ GOOD ("-35791394m", -35791394 * MIN),
+ GOOD ("-35791394m7s", -35791394 * MIN + 7),
+ BAD ("-35791394m-9s"),
+
};
int fail = 0;
int i;
diff --git a/src/lib/krb5/krb/x-deltat.y b/src/lib/krb5/krb/x-deltat.y
index be53ce3c6..37aa79cbb 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: