2121#include "lualib.h"
2222
2323
24- #define MAXUNICODE 0x10FFFF
24+ #define MAXUNICODE 0x10FFFFu
25+
26+ #define MAXUTF 0x7FFFFFFFu
2527
2628/*
27- ** Integer type for decoded UTF-8 values; MAXUNICODE needs 21 bits.
29+ ** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits.
2830*/
29- #if LUAI_BITSINT >= 21
31+ #if LUAI_BITSINT >= 31
3032typedef unsigned int utfint ;
3133#else
3234typedef unsigned long utfint ;
@@ -46,51 +48,60 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) {
4648
4749
4850/*
49- ** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid.
51+ ** Decode one UTF-8 sequence, returning NULL if byte sequence is
52+ ** invalid. The array 'limits' stores the minimum value for each
53+ ** sequence length, to check for overlong representations. Its first
54+ ** entry forces an error for non-ascii bytes with no continuation
55+ ** bytes (count == 0).
5056*/
51- static const char * utf8_decode (const char * o , utfint * val ) {
52- static const unsigned int limits [] = { 0xFF , 0x7F , 0x7FF , 0xFFFF };
53- const unsigned char * s = ( const unsigned char * ) o ;
54- unsigned int c = s [0 ];
57+ static const char * utf8_decode (const char * s , utfint * val , int strict ) {
58+ static const utfint limits [] =
59+ {~( utfint ) 0 , 0x80 , 0x800 , 0x10000u , 0x200000u , 0x4000000u } ;
60+ unsigned int c = ( unsigned char ) s [0 ];
5561 utfint res = 0 ; /* final result */
5662 if (c < 0x80 ) /* ascii? */
5763 res = c ;
5864 else {
5965 int count = 0 ; /* to count number of continuation bytes */
60- while ( c & 0x40 ) { /* still have continuation bytes? */
61- int cc = s [++ count ]; /* read next byte */
66+ for (; c & 0x40 ; c <<= 1 ) { /* while it needs continuation bytes... */
67+ unsigned int cc = ( unsigned char ) s [++ count ]; /* read next byte */
6268 if ((cc & 0xC0 ) != 0x80 ) /* not a continuation byte? */
6369 return NULL ; /* invalid byte sequence */
6470 res = (res << 6 ) | (cc & 0x3F ); /* add lower 6 bits from cont. byte */
65- c <<= 1 ; /* to test next bit */
6671 }
6772 res |= ((utfint )(c & 0x7F ) << (count * 5 )); /* add first byte */
68- if (count > 3 || res > MAXUNICODE || res <= limits [count ])
73+ if (count > 5 || res > MAXUTF || res < limits [count ])
6974 return NULL ; /* invalid byte sequence */
7075 s += count ; /* skip continuation bytes read */
7176 }
77+ if (strict ) {
78+ /* check for invalid code points; too large or surrogates */
79+ if (res > MAXUNICODE || (0xD800u <= res && res <= 0xDFFFu ))
80+ return NULL ;
81+ }
7282 if (val ) * val = res ;
73- return ( const char * ) s + 1 ; /* +1 to include first byte */
83+ return s + 1 ; /* +1 to include first byte */
7484}
7585
7686
7787/*
78- ** utf8len(s [, i [, j]] ) --> number of characters that start in the
79- ** range [i,j], or nil + current position if 's' is not well formed in
80- ** that interval
88+ ** utf8len(s [, i [, j [, nonstrict]]] ) --> number of characters that
89+ ** start in the range [i,j], or nil + current position if 's' is not
90+ ** well formed in that interval
8191*/
8292static int utflen (lua_State * L ) {
8393 lua_Integer n = 0 ; /* counter for the number of characters */
8494 size_t len ; /* string length in bytes */
8595 const char * s = luaL_checklstring (L , 1 , & len );
8696 lua_Integer posi = u_posrelat (luaL_optinteger (L , 2 , 1 ), len );
8797 lua_Integer posj = u_posrelat (luaL_optinteger (L , 3 , -1 ), len );
98+ int nonstrict = lua_toboolean (L , 4 );
8899 luaL_argcheck (L , 1 <= posi && -- posi <= (lua_Integer )len , 2 ,
89100 "initial position out of string" );
90101 luaL_argcheck (L , -- posj < (lua_Integer )len , 3 ,
91102 "final position out of string" );
92103 while (posi <= posj ) {
93- const char * s1 = utf8_decode (s + posi , NULL );
104+ const char * s1 = utf8_decode (s + posi , NULL , ! nonstrict );
94105 if (s1 == NULL ) { /* conversion error? */
95106 lua_pushnil (L ); /* return nil ... */
96107 lua_pushinteger (L , posi + 1 ); /* ... and current position */
@@ -105,14 +116,15 @@ static int utflen (lua_State *L) {
105116
106117
107118/*
108- ** codepoint(s, [i, [j]]) -> returns codepoints for all characters
109- ** that start in the range [i,j]
119+ ** codepoint(s, [i, [j [, nonstrict]]]) -> returns codepoints for all
120+ ** characters that start in the range [i,j]
110121*/
111122static int codepoint (lua_State * L ) {
112123 size_t len ;
113124 const char * s = luaL_checklstring (L , 1 , & len );
114125 lua_Integer posi = u_posrelat (luaL_optinteger (L , 2 , 1 ), len );
115126 lua_Integer pose = u_posrelat (luaL_optinteger (L , 3 , posi ), len );
127+ int nonstrict = lua_toboolean (L , 4 );
116128 int n ;
117129 const char * se ;
118130 luaL_argcheck (L , posi >= 1 , 2 , "out of range" );
@@ -126,7 +138,7 @@ static int codepoint (lua_State *L) {
126138 se = s + pose ; /* string end */
127139 for (s += posi - 1 ; s < se ;) {
128140 utfint code ;
129- s = utf8_decode (s , & code );
141+ s = utf8_decode (s , & code , ! nonstrict );
130142 if (s == NULL )
131143 return luaL_error (L , "invalid UTF-8 code" );
132144 lua_pushinteger (L , code );
@@ -137,8 +149,8 @@ static int codepoint (lua_State *L) {
137149
138150
139151static void pushutfchar (lua_State * L , int arg ) {
140- lua_Integer code = luaL_checkinteger (L , arg );
141- luaL_argcheck (L , 0 <= code && code <= MAXUNICODE , arg , "value out of range" );
152+ lua_Unsigned code = ( lua_Unsigned ) luaL_checkinteger (L , arg );
153+ luaL_argcheck (L , code <= MAXUTF , arg , "value out of range" );
142154 lua_pushfstring (L , "%U" , (long )code );
143155}
144156
@@ -209,7 +221,7 @@ static int byteoffset (lua_State *L) {
209221}
210222
211223
212- static int iter_aux (lua_State * L ) {
224+ static int iter_aux (lua_State * L , int strict ) {
213225 size_t len ;
214226 const char * s = luaL_checklstring (L , 1 , & len );
215227 lua_Integer n = lua_tointeger (L , 2 ) - 1 ;
@@ -223,8 +235,8 @@ static int iter_aux (lua_State *L) {
223235 return 0 ; /* no more codepoints */
224236 else {
225237 utfint code ;
226- const char * next = utf8_decode (s + n , & code );
227- if (next == NULL || iscont ( next ) )
238+ const char * next = utf8_decode (s + n , & code , strict );
239+ if (next == NULL )
228240 return luaL_error (L , "invalid UTF-8 code" );
229241 lua_pushinteger (L , n + 1 );
230242 lua_pushinteger (L , code );
@@ -233,17 +245,27 @@ static int iter_aux (lua_State *L) {
233245}
234246
235247
248+ static int iter_auxstrict (lua_State * L ) {
249+ return iter_aux (L , 1 );
250+ }
251+
252+ static int iter_auxnostrict (lua_State * L ) {
253+ return iter_aux (L , 0 );
254+ }
255+
256+
236257static int iter_codes (lua_State * L ) {
258+ int nonstrict = lua_toboolean (L , 2 );
237259 luaL_checkstring (L , 1 );
238- lua_pushcfunction (L , iter_aux );
260+ lua_pushcfunction (L , nonstrict ? iter_auxnostrict : iter_auxstrict );
239261 lua_pushvalue (L , 1 );
240262 lua_pushinteger (L , 0 );
241263 return 3 ;
242264}
243265
244266
245267/* pattern to match a single UTF-8 character */
246- #define UTF8PATT "[\0-\x7F\xC2-\xF4 ][\x80-\xBF]*"
268+ #define UTF8PATT "[\0-\x7F\xC2-\xFD ][\x80-\xBF]*"
247269
248270
249271static const luaL_Reg funcs [] = {
0 commit comments