added some error checks for error literals and smptr literals

This commit is contained in:
hyung-hwan 2018-02-17 16:01:27 +00:00
parent de0715e302
commit 22127d384f
4 changed files with 37 additions and 39 deletions

View File

@ -83,6 +83,8 @@ static char* synerrstr[] =
"wrong character literal", "wrong character literal",
"invalid numeric literal", "invalid numeric literal",
"out of integer range", "out of integer range",
"wrong error literal",
"wrong smptr literal",
"sudden end of input", "sudden end of input",
"( expected", "( expected",

View File

@ -94,6 +94,8 @@ enum hcl_synerrnum_t
HCL_SYNERR_CHARLIT, /* wrong character literal */ HCL_SYNERR_CHARLIT, /* wrong character literal */
HCL_SYNERR_RADNUMLIT , /* invalid numeric literal with radix */ HCL_SYNERR_RADNUMLIT , /* invalid numeric literal with radix */
HCL_SYNERR_INTRANGE, /* integer range error */ HCL_SYNERR_INTRANGE, /* integer range error */
HCL_SYNERR_ERRORLIT, /* wrong error literal */
HCL_SYNERR_SMPTRLIT, /* wrong smptr literal */
HCL_SYNERR_EOF, /* sudden end of input */ HCL_SYNERR_EOF, /* sudden end of input */
HCL_SYNERR_LPAREN, /* ( expected */ HCL_SYNERR_LPAREN, /* ( expected */
@ -236,38 +238,6 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t;
#endif #endif
#if 0
/*
* OOP encoding
* An object pointer(OOP) is an ordinary pointer value to an object.
* but some simple numeric values are also encoded into OOP using a simple
* bit-shifting and masking.
*
* A real OOP is stored without any bit-shifting while a non-OOP value encoded
* in an OOP is bit-shifted to the left by 2 and the 2 least-significant bits
* are set to 1 or 2.
*
* This scheme works because the object allocators aligns the object size to
* a multiple of sizeof(hcl_oop_t). This way, the 2 least-significant bits
* of a real OOP are always 0s.
*/
#define HCL_OOP_TAG_BITS 2
#define HCL_OOP_TAG_SMOOI 1
#define HCL_OOP_TAG_CHAR 2
#define HCL_OOP_IS_NUMERIC(oop) (((hcl_oow_t)oop) & (HCL_OOP_TAG_SMOOI | HCL_OOP_TAG_CHAR))
#define HCL_OOP_IS_POINTER(oop) (!HCL_OOP_IS_NUMERIC(oop))
#define HCL_OOP_GET_TAG(oop) (((hcl_oow_t)oop) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS))
#define HCL_OOP_IS_SMOOI(oop) (((hcl_ooi_t)oop) & HCL_OOP_TAG_SMOOI)
#define HCL_OOP_IS_CHAR(oop) (((hcl_oow_t)oop) & HCL_OOP_TAG_CHAR)
#define HCL_SMOOI_TO_OOP(num) ((hcl_oop_t)((((hcl_ooi_t)(num)) << HCL_OOP_TAG_BITS) | HCL_OOP_TAG_SMOOI))
#define HCL_OOP_TO_SMOOI(oop) (((hcl_ooi_t)oop) >> HCL_OOP_TAG_BITS)
#define HCL_CHAR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << HCL_OOP_TAG_BITS) | HCL_OOP_TAG_CHAR))
#define HCL_OOP_TO_CHAR(oop) (((hcl_oow_t)oop) >> HCL_OOP_TAG_BITS)
#else
/* /*
* OOP encoding * OOP encoding
* An object pointer(OOP) is an ordinary pointer value to an object. * An object pointer(OOP) is an ordinary pointer value to an object.
@ -327,8 +297,6 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t;
#define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) #define HCL_OOP_TO_ERROR(oop) (((hcl_oow_t)oop) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO))
#define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR)) #define HCL_ERROR_TO_OOP(num) ((hcl_oop_t)((((hcl_oow_t)(num)) << (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_LO)) | HCL_OOP_TAG_ERROR))
#endif
/* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits /* SMOOI takes up 62 bit on a 64-bit architecture and 30 bits
* on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits * on a 32-bit architecture. The absolute value takes up 61 bits and 29 bits
* respectively for the 1 sign bit. */ * respectively for the 1 sign bit. */
@ -341,6 +309,21 @@ typedef struct hcl_obj_word_t* hcl_oop_word_t;
#define HCL_SMOOI_MIN (-HCL_SMOOI_MAX) #define HCL_SMOOI_MIN (-HCL_SMOOI_MAX)
#define HCL_IN_SMOOI_RANGE(ooi) ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX) #define HCL_IN_SMOOI_RANGE(ooi) ((ooi) >= HCL_SMOOI_MIN && (ooi) <= HCL_SMOOI_MAX)
/* SMPTR is a special value which has been devised to encode an address value
* whose low HCL_OOP_TAG_BITS_LO bits are 0. its class is SmallPointer. A pointer
* returned by most of system functions would be aligned to the pointer size.
* you can use the followings macros when converting such a pointer without loss. */
#define HCL_IN_SMPTR_RANGE(ptr) ((((hcl_oow_t)ptr) & HCL_LBMASK(hcl_oow_t, HCL_OOP_TAG_BITS_LO)) == 0)
#define HCL_CHAR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI)
#define HCL_CHAR_MIN 0
#define HCL_CHAR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI))
#define HCL_ERROR_BITS (HCL_OOI_BITS - HCL_OOP_TAG_BITS_LO - HCL_OOP_TAG_BITS_HI)
#define HCL_ERROR_MIN 0
#define HCL_ERROR_MAX (~((hcl_oow_t)0) >> (HCL_OOP_TAG_BITS_LO + HCL_OOP_TAG_BITS_HI))
/* TODO: There are untested code where smint is converted to hcl_oow_t. /* TODO: There are untested code where smint is converted to hcl_oow_t.
* for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t. * for example, the spec making macro treats the number as hcl_oow_t instead of hcl_ooi_t.
* as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX. * as of this writing, i skip testing that part with the spec value exceeding HCL_SMOOI_MAX.

View File

@ -191,7 +191,7 @@ next:
} }
else if (HCL_OOP_IS_SMPTR(obj)) else if (HCL_OOP_IS_SMPTR(obj))
{ {
if (outbfmt(hcl, mask, "#\\p%zu", (hcl_oow_t)HCL_OOP_TO_SMPTR(obj)) <= -1) return -1; if (outbfmt(hcl, mask, "#\\p%zX", (hcl_oow_t)HCL_OOP_TO_SMPTR(obj)) <= -1) return -1;
goto done; goto done;
} }
else if (HCL_OOP_IS_ERROR(obj)) else if (HCL_OOP_IS_ERROR(obj))

View File

@ -823,12 +823,13 @@ static int get_sharp_token (hcl_t* hcl)
if (TOKEN_NAME_LEN(hcl) >= 4) if (TOKEN_NAME_LEN(hcl) >= 4)
{ {
if (hcl->c->tok.name.ptr[2] == 'p') if (TOKEN_NAME_CHAR(hcl, 2) == 'P' || TOKEN_NAME_CHAR(hcl, 2) == 'p')
{ {
SET_TOKEN_TYPE (hcl, HCL_IOTOK_SMPTRLIT); SET_TOKEN_TYPE (hcl, HCL_IOTOK_SMPTRLIT);
goto hexcharlit; goto hexcharlit;
} }
else if (hcl->c->tok.name.ptr[2] == 'x' || hcl->c->tok.name.ptr[2] == 'u') else if (TOKEN_NAME_CHAR(hcl, 2) == 'X' || TOKEN_NAME_CHAR(hcl, 2) == 'x' ||
TOKEN_NAME_CHAR(hcl, 2) == 'U' || TOKEN_NAME_CHAR(hcl, 2) == 'u')
{ {
hcl_oow_t i; hcl_oow_t i;
@ -845,7 +846,7 @@ static int get_sharp_token (hcl_t* hcl)
c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */ c = c * 16 + CHAR_TO_NUM(hcl->c->tok.name.ptr[i], 16); /* don't care if it is for 'p' */
} }
} }
else if (hcl->c->tok.name.ptr[2] == 'e') else if (TOKEN_NAME_CHAR(hcl, 2) == 'E' || TOKEN_NAME_CHAR(hcl, 2) == 'e')
{ {
hcl_oow_t i; hcl_oow_t i;
for (i = 3; i < TOKEN_NAME_LEN(hcl); i++) for (i = 3; i < TOKEN_NAME_LEN(hcl); i++)
@ -1756,7 +1757,6 @@ static int read_object (hcl_t* hcl)
switch (TOKEN_TYPE(hcl)) switch (TOKEN_TYPE(hcl))
{ {
default: default:
HCL_ASSERT (hcl, !"should never happen - invalid token type");
hcl_seterrbfmt (hcl, HCL_EINTERN, "invalid token encountered - %d %.*js", hcl_seterrbfmt (hcl, HCL_EINTERN, "invalid token encountered - %d %.*js",
TOKEN_TYPE(hcl), TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl)); TOKEN_TYPE(hcl), TOKEN_NAME_LEN(hcl), TOKEN_NAME_PTR(hcl));
return -1; return -1;
@ -1960,6 +1960,13 @@ static int read_object (hcl_t* hcl)
v = v * 16 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 16); v = v * 16 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 16);
} }
if (!HCL_IN_SMPTR_RANGE(v))
{
hcl_setsynerr (hcl, HCL_SYNERR_SMPTRLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
return -1;
}
obj = HCL_SMPTR_TO_OOP(v); obj = HCL_SMPTR_TO_OOP(v);
break; break;
} }
@ -1974,6 +1981,12 @@ static int read_object (hcl_t* hcl)
{ {
HCL_ASSERT (hcl, is_digitchar(TOKEN_NAME_CHAR(hcl, i))); HCL_ASSERT (hcl, is_digitchar(TOKEN_NAME_CHAR(hcl, i)));
v = v * 10 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 10); v = v * 10 + CHAR_TO_NUM(TOKEN_NAME_CHAR(hcl, i), 10);
if (v > HCL_ERROR_MAX)
{
hcl_setsynerr (hcl, HCL_SYNERR_ERRORLIT, TOKEN_LOC(hcl), TOKEN_NAME(hcl));
return -1;
}
} }
obj = HCL_ERROR_TO_OOP(v); obj = HCL_ERROR_TO_OOP(v);