diff options
author | Philipp Janda <siffiejoe@gmx.net> | 2016-01-22 15:58:48 +0100 |
---|---|---|
committer | Philipp Janda <siffiejoe@gmx.net> | 2016-01-22 15:58:48 +0100 |
commit | ca85188590e677edcc9290d29e69a3692187c826 (patch) | |
tree | 6223894654ff62468f1086423caf31f459e7861b /lstrlib.c | |
parent | abf4ea9645ce3ff0c390a57ab3e3e4f82d9a4035 (diff) | |
download | lua-compat-5.3-ca85188590e677edcc9290d29e69a3692187c826.tar.gz lua-compat-5.3-ca85188590e677edcc9290d29e69a3692187c826.tar.bz2 lua-compat-5.3-ca85188590e677edcc9290d29e69a3692187c826.zip |
Update backports.
The backports of lstrlib.c, ltablib.c, and lutf8lib.c have been updated
to Lua version 5.3.2.
Diffstat (limited to 'lstrlib.c')
-rw-r--r-- | lstrlib.c | 277 |
1 files changed, 200 insertions, 77 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.221 2014/12/11 14:03:07 roberto Exp $ | 2 | ** $Id: lstrlib.c,v 1.239 2015/11/25 16:28:17 roberto Exp $ |
3 | ** Standard library for string operations and pattern-matching | 3 | ** Standard library for string operations and pattern-matching |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | 12 | ||
13 | #include <ctype.h> | 13 | #include <ctype.h> |
14 | #include <float.h> | ||
14 | #include <limits.h> | 15 | #include <limits.h> |
15 | #include <stddef.h> | 16 | #include <stddef.h> |
16 | #include <stdio.h> | 17 | #include <stdio.h> |
@@ -40,8 +41,10 @@ | |||
40 | ** Some sizes are better limited to fit in 'int', but must also fit in | 41 | ** Some sizes are better limited to fit in 'int', but must also fit in |
41 | ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) | 42 | ** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) |
42 | */ | 43 | */ |
44 | #define MAX_SIZET ((size_t)(~(size_t)0)) | ||
45 | |||
43 | #define MAXSIZE \ | 46 | #define MAXSIZE \ |
44 | (sizeof(size_t) < sizeof(int) ? (~(size_t)0) : (size_t)(INT_MAX)) | 47 | (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) |
45 | 48 | ||
46 | 49 | ||
47 | 50 | ||
@@ -70,7 +73,7 @@ static int str_sub (lua_State *L) { | |||
70 | if (start < 1) start = 1; | 73 | if (start < 1) start = 1; |
71 | if (end > (lua_Integer)l) end = l; | 74 | if (end > (lua_Integer)l) end = l; |
72 | if (start <= end) | 75 | if (start <= end) |
73 | lua_pushlstring(L, s + start - 1, (size_t)(end - start + 1)); | 76 | lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); |
74 | else lua_pushliteral(L, ""); | 77 | else lua_pushliteral(L, ""); |
75 | return 1; | 78 | return 1; |
76 | } | 79 | } |
@@ -149,9 +152,9 @@ static int str_byte (lua_State *L) { | |||
149 | if (posi < 1) posi = 1; | 152 | if (posi < 1) posi = 1; |
150 | if (pose > (lua_Integer)l) pose = l; | 153 | if (pose > (lua_Integer)l) pose = l; |
151 | if (posi > pose) return 0; /* empty interval; return no values */ | 154 | if (posi > pose) return 0; /* empty interval; return no values */ |
152 | n = (int)(pose - posi + 1); | 155 | if (pose - posi >= INT_MAX) /* arithmetic overflow? */ |
153 | if (posi + n <= pose) /* arithmetic overflow? */ | ||
154 | return luaL_error(L, "string slice too long"); | 156 | return luaL_error(L, "string slice too long"); |
157 | n = (int)(pose - posi) + 1; | ||
155 | luaL_checkstack(L, n, "string slice too long"); | 158 | luaL_checkstack(L, n, "string slice too long"); |
156 | for (i=0; i<n; i++) | 159 | for (i=0; i<n; i++) |
157 | lua_pushinteger(L, uchar(s[posi+i-1])); | 160 | lua_pushinteger(L, uchar(s[posi+i-1])); |
@@ -207,11 +210,12 @@ static int str_dump (lua_State *L) { | |||
207 | 210 | ||
208 | 211 | ||
209 | typedef struct MatchState { | 212 | typedef struct MatchState { |
210 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ | ||
211 | const char *src_init; /* init of source string */ | 213 | const char *src_init; /* init of source string */ |
212 | const char *src_end; /* end ('\0') of source string */ | 214 | const char *src_end; /* end ('\0') of source string */ |
213 | const char *p_end; /* end ('\0') of pattern */ | 215 | const char *p_end; /* end ('\0') of pattern */ |
214 | lua_State *L; | 216 | lua_State *L; |
217 | size_t nrep; /* limit to avoid non-linear complexity */ | ||
218 | int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ | ||
215 | int level; /* total number of captures (finished or unfinished) */ | 219 | int level; /* total number of captures (finished or unfinished) */ |
216 | struct { | 220 | struct { |
217 | const char *init; | 221 | const char *init; |
@@ -230,6 +234,17 @@ static const char *match (MatchState *ms, const char *s, const char *p); | |||
230 | #endif | 234 | #endif |
231 | 235 | ||
232 | 236 | ||
237 | /* | ||
238 | ** parameters to control the maximum number of operators handled in | ||
239 | ** a match (to avoid non-linear complexity). The maximum will be: | ||
240 | ** (subject length) * A_REPS + B_REPS | ||
241 | */ | ||
242 | #if !defined(A_REPS) | ||
243 | #define A_REPS 4 | ||
244 | #define B_REPS 100000 | ||
245 | #endif | ||
246 | |||
247 | |||
233 | #define L_ESC '%' | 248 | #define L_ESC '%' |
234 | #define SPECIALS "^$*+?.([%-" | 249 | #define SPECIALS "^$*+?.([%-" |
235 | 250 | ||
@@ -487,6 +502,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) { | |||
487 | s = NULL; /* fail */ | 502 | s = NULL; /* fail */ |
488 | } | 503 | } |
489 | else { /* matched once */ | 504 | else { /* matched once */ |
505 | if (ms->nrep-- == 0) | ||
506 | luaL_error(ms->L, "pattern too complex"); | ||
490 | switch (*ep) { /* handle optional suffix */ | 507 | switch (*ep) { /* handle optional suffix */ |
491 | case '?': { /* optional */ | 508 | case '?': { /* optional */ |
492 | const char *res; | 509 | const char *res; |
@@ -499,7 +516,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) { | |||
499 | } | 516 | } |
500 | case '+': /* 1 or more repetitions */ | 517 | case '+': /* 1 or more repetitions */ |
501 | s++; /* 1 match already done */ | 518 | s++; /* 1 match already done */ |
502 | /* go through */ | 519 | /* FALLTHROUGH */ |
503 | case '*': /* 0 or more repetitions */ | 520 | case '*': /* 0 or more repetitions */ |
504 | s = max_expand(ms, s, p, ep); | 521 | s = max_expand(ms, s, p, ep); |
505 | break; | 522 | break; |
@@ -554,7 +571,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s, | |||
554 | ptrdiff_t l = ms->capture[i].len; | 571 | ptrdiff_t l = ms->capture[i].len; |
555 | if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); | 572 | if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); |
556 | if (l == CAP_POSITION) | 573 | if (l == CAP_POSITION) |
557 | lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); | 574 | lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); |
558 | else | 575 | else |
559 | lua_pushlstring(ms->L, ms->capture[i].init, l); | 576 | lua_pushlstring(ms->L, ms->capture[i].init, l); |
560 | } | 577 | } |
@@ -583,6 +600,26 @@ static int nospecials (const char *p, size_t l) { | |||
583 | } | 600 | } |
584 | 601 | ||
585 | 602 | ||
603 | static void prepstate (MatchState *ms, lua_State *L, | ||
604 | const char *s, size_t ls, const char *p, size_t lp) { | ||
605 | ms->L = L; | ||
606 | ms->matchdepth = MAXCCALLS; | ||
607 | ms->src_init = s; | ||
608 | ms->src_end = s + ls; | ||
609 | ms->p_end = p + lp; | ||
610 | if (ls < (MAX_SIZET - B_REPS) / A_REPS) | ||
611 | ms->nrep = A_REPS * ls + B_REPS; | ||
612 | else /* overflow (very long subject) */ | ||
613 | ms->nrep = MAX_SIZET; /* no limit */ | ||
614 | } | ||
615 | |||
616 | |||
617 | static void reprepstate (MatchState *ms) { | ||
618 | ms->level = 0; | ||
619 | lua_assert(ms->matchdepth == MAXCCALLS); | ||
620 | } | ||
621 | |||
622 | |||
586 | static int str_find_aux (lua_State *L, int find) { | 623 | static int str_find_aux (lua_State *L, int find) { |
587 | size_t ls, lp; | 624 | size_t ls, lp; |
588 | const char *s = luaL_checklstring(L, 1, &ls); | 625 | const char *s = luaL_checklstring(L, 1, &ls); |
@@ -598,8 +635,8 @@ static int str_find_aux (lua_State *L, int find) { | |||
598 | /* do a plain search */ | 635 | /* do a plain search */ |
599 | const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); | 636 | const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); |
600 | if (s2) { | 637 | if (s2) { |
601 | lua_pushinteger(L, s2 - s + 1); | 638 | lua_pushinteger(L, (s2 - s) + 1); |
602 | lua_pushinteger(L, s2 - s + lp); | 639 | lua_pushinteger(L, (s2 - s) + lp); |
603 | return 2; | 640 | return 2; |
604 | } | 641 | } |
605 | } | 642 | } |
@@ -610,18 +647,13 @@ static int str_find_aux (lua_State *L, int find) { | |||
610 | if (anchor) { | 647 | if (anchor) { |
611 | p++; lp--; /* skip anchor character */ | 648 | p++; lp--; /* skip anchor character */ |
612 | } | 649 | } |
613 | ms.L = L; | 650 | prepstate(&ms, L, s, ls, p, lp); |
614 | ms.matchdepth = MAXCCALLS; | ||
615 | ms.src_init = s; | ||
616 | ms.src_end = s + ls; | ||
617 | ms.p_end = p + lp; | ||
618 | do { | 651 | do { |
619 | const char *res; | 652 | const char *res; |
620 | ms.level = 0; | 653 | reprepstate(&ms); |
621 | lua_assert(ms.matchdepth == MAXCCALLS); | ||
622 | if ((res=match(&ms, s1, p)) != NULL) { | 654 | if ((res=match(&ms, s1, p)) != NULL) { |
623 | if (find) { | 655 | if (find) { |
624 | lua_pushinteger(L, s1 - s + 1); /* start */ | 656 | lua_pushinteger(L, (s1 - s) + 1); /* start */ |
625 | lua_pushinteger(L, res - s); /* end */ | 657 | lua_pushinteger(L, res - s); /* end */ |
626 | return push_captures(&ms, NULL, 0) + 2; | 658 | return push_captures(&ms, NULL, 0) + 2; |
627 | } | 659 | } |
@@ -645,29 +677,26 @@ static int str_match (lua_State *L) { | |||
645 | } | 677 | } |
646 | 678 | ||
647 | 679 | ||
680 | /* state for 'gmatch' */ | ||
681 | typedef struct GMatchState { | ||
682 | const char *src; /* current position */ | ||
683 | const char *p; /* pattern */ | ||
684 | MatchState ms; /* match state */ | ||
685 | } GMatchState; | ||
686 | |||
687 | |||
648 | static int gmatch_aux (lua_State *L) { | 688 | static int gmatch_aux (lua_State *L) { |
649 | MatchState ms; | 689 | GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); |
650 | size_t ls, lp; | ||
651 | const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); | ||
652 | const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); | ||
653 | const char *src; | 690 | const char *src; |
654 | ms.L = L; | 691 | for (src = gm->src; src <= gm->ms.src_end; src++) { |
655 | ms.matchdepth = MAXCCALLS; | ||
656 | ms.src_init = s; | ||
657 | ms.src_end = s+ls; | ||
658 | ms.p_end = p + lp; | ||
659 | for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); | ||
660 | src <= ms.src_end; | ||
661 | src++) { | ||
662 | const char *e; | 692 | const char *e; |
663 | ms.level = 0; | 693 | reprepstate(&gm->ms); |
664 | lua_assert(ms.matchdepth == MAXCCALLS); | 694 | if ((e = match(&gm->ms, src, gm->p)) != NULL) { |
665 | if ((e = match(&ms, src, p)) != NULL) { | 695 | if (e == src) /* empty match? */ |
666 | lua_Integer newstart = e-s; | 696 | gm->src =src + 1; /* go at least one position */ |
667 | if (e == src) newstart++; /* empty match? go at least one position */ | 697 | else |
668 | lua_pushinteger(L, newstart); | 698 | gm->src = e; |
669 | lua_replace(L, lua_upvalueindex(3)); | 699 | return push_captures(&gm->ms, src, e); |
670 | return push_captures(&ms, src, e); | ||
671 | } | 700 | } |
672 | } | 701 | } |
673 | return 0; /* not found */ | 702 | return 0; /* not found */ |
@@ -675,10 +704,14 @@ static int gmatch_aux (lua_State *L) { | |||
675 | 704 | ||
676 | 705 | ||
677 | static int gmatch (lua_State *L) { | 706 | static int gmatch (lua_State *L) { |
678 | luaL_checkstring(L, 1); | 707 | size_t ls, lp; |
679 | luaL_checkstring(L, 2); | 708 | const char *s = luaL_checklstring(L, 1, &ls); |
680 | lua_settop(L, 2); | 709 | const char *p = luaL_checklstring(L, 2, &lp); |
681 | lua_pushinteger(L, 0); | 710 | GMatchState *gm; |
711 | lua_settop(L, 2); /* keep them on closure to avoid being collected */ | ||
712 | gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); | ||
713 | prepstate(&gm->ms, L, s, ls, p, lp); | ||
714 | gm->src = s; gm->p = p; | ||
682 | lua_pushcclosure(L, gmatch_aux, 3); | 715 | lua_pushcclosure(L, gmatch_aux, 3); |
683 | return 1; | 716 | return 1; |
684 | } | 717 | } |
@@ -760,17 +793,11 @@ static int str_gsub (lua_State *L) { | |||
760 | if (anchor) { | 793 | if (anchor) { |
761 | p++; lp--; /* skip anchor character */ | 794 | p++; lp--; /* skip anchor character */ |
762 | } | 795 | } |
763 | ms.L = L; | 796 | prepstate(&ms, L, src, srcl, p, lp); |
764 | ms.matchdepth = MAXCCALLS; | ||
765 | ms.src_init = src; | ||
766 | ms.src_end = src+srcl; | ||
767 | ms.p_end = p + lp; | ||
768 | while (n < max_s) { | 797 | while (n < max_s) { |
769 | const char *e; | 798 | const char *e; |
770 | ms.level = 0; | 799 | reprepstate(&ms); |
771 | lua_assert(ms.matchdepth == MAXCCALLS); | 800 | if ((e = match(&ms, src, p)) != NULL) { |
772 | e = match(&ms, src, p); | ||
773 | if (e) { | ||
774 | n++; | 801 | n++; |
775 | add_value(&ms, &b, src, e, tr); | 802 | add_value(&ms, &b, src, e, tr); |
776 | } | 803 | } |
@@ -797,17 +824,102 @@ static int str_gsub (lua_State *L) { | |||
797 | ** ======================================================= | 824 | ** ======================================================= |
798 | */ | 825 | */ |
799 | 826 | ||
800 | /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ | 827 | #if !defined(lua_number2strx) /* { */ |
801 | #define MAX_ITEM 512 | 828 | |
829 | /* | ||
830 | ** Hexadecimal floating-point formatter | ||
831 | */ | ||
832 | |||
833 | #include <locale.h> | ||
834 | #include <math.h> | ||
835 | |||
836 | #define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) | ||
837 | |||
838 | |||
839 | /* | ||
840 | ** Number of bits that goes into the first digit. It can be any value | ||
841 | ** between 1 and 4; the following definition tries to align the number | ||
842 | ** to nibble boundaries by making what is left after that first digit a | ||
843 | ** multiple of 4. | ||
844 | */ | ||
845 | #define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) | ||
846 | |||
847 | |||
848 | /* | ||
849 | ** Add integer part of 'x' to buffer and return new 'x' | ||
850 | */ | ||
851 | static lua_Number adddigit (char *buff, int n, lua_Number x) { | ||
852 | lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ | ||
853 | int d = (int)dd; | ||
854 | buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ | ||
855 | return x - dd; /* return what is left */ | ||
856 | } | ||
857 | |||
858 | |||
859 | static int num2straux (char *buff, int sz, lua_Number x) { | ||
860 | if (x != x || x == HUGE_VAL || x == -HUGE_VAL) /* inf or NaN? */ | ||
861 | return l_sprintf(buff, sz, LUA_NUMBER_FMT, x); /* equal to '%g' */ | ||
862 | else if (x == 0) { /* can be -0... */ | ||
863 | /* create "0" or "-0" followed by exponent */ | ||
864 | return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", x); | ||
865 | } | ||
866 | else { | ||
867 | int e; | ||
868 | lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ | ||
869 | int n = 0; /* character count */ | ||
870 | if (m < 0) { /* is number negative? */ | ||
871 | buff[n++] = '-'; /* add signal */ | ||
872 | m = -m; /* make it positive */ | ||
873 | } | ||
874 | buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ | ||
875 | m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ | ||
876 | e -= L_NBFD; /* this digit goes before the radix point */ | ||
877 | if (m > 0) { /* more digits? */ | ||
878 | buff[n++] = lua_getlocaledecpoint(); /* add radix point */ | ||
879 | do { /* add as many digits as needed */ | ||
880 | m = adddigit(buff, n++, m * 16); | ||
881 | } while (m > 0); | ||
882 | } | ||
883 | n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ | ||
884 | lua_assert(n < sz); | ||
885 | return n; | ||
886 | } | ||
887 | } | ||
888 | |||
889 | |||
890 | static int lua_number2strx (lua_State *L, char *buff, int sz, | ||
891 | const char *fmt, lua_Number x) { | ||
892 | int n = num2straux(buff, sz, x); | ||
893 | if (fmt[SIZELENMOD] == 'A') { | ||
894 | int i; | ||
895 | for (i = 0; i < n; i++) | ||
896 | buff[i] = toupper(uchar(buff[i])); | ||
897 | } | ||
898 | else if (fmt[SIZELENMOD] != 'a') | ||
899 | luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); | ||
900 | return n; | ||
901 | } | ||
902 | |||
903 | #endif /* } */ | ||
904 | |||
905 | |||
906 | /* | ||
907 | ** Maximum size of each formatted item. This maximum size is produced | ||
908 | ** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', | ||
909 | ** and '\0') + number of decimal digits to represent maxfloat (which | ||
910 | ** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra | ||
911 | ** expenses", such as locale-dependent stuff) | ||
912 | */ | ||
913 | #define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) | ||
914 | |||
802 | 915 | ||
803 | /* valid flags in a format specification */ | 916 | /* valid flags in a format specification */ |
804 | #define FLAGS "-+ #0" | 917 | #define FLAGS "-+ #0" |
805 | 918 | ||
806 | /* | 919 | /* |
807 | ** maximum size of each format specification (such as "%-099.99d") | 920 | ** maximum size of each format specification (such as "%-099.99d") |
808 | ** (+2 for length modifiers; +10 accounts for %99.99x plus margin of error) | ||
809 | */ | 921 | */ |
810 | #define MAX_FORMAT (sizeof(FLAGS) + 2 + 10) | 922 | #define MAX_FORMAT 32 |
811 | 923 | ||
812 | 924 | ||
813 | static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | 925 | static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { |
@@ -822,9 +934,9 @@ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { | |||
822 | else if (*s == '\0' || iscntrl(uchar(*s))) { | 934 | else if (*s == '\0' || iscntrl(uchar(*s))) { |
823 | char buff[10]; | 935 | char buff[10]; |
824 | if (!isdigit(uchar(*(s+1)))) | 936 | if (!isdigit(uchar(*(s+1)))) |
825 | sprintf(buff, "\\%d", (int)uchar(*s)); | 937 | l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); |
826 | else | 938 | else |
827 | sprintf(buff, "\\%03d", (int)uchar(*s)); | 939 | l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); |
828 | luaL_addstring(b, buff); | 940 | luaL_addstring(b, buff); |
829 | } | 941 | } |
830 | else | 942 | else |
@@ -849,8 +961,8 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | |||
849 | if (isdigit(uchar(*p))) | 961 | if (isdigit(uchar(*p))) |
850 | luaL_error(L, "invalid format (width or precision too long)"); | 962 | luaL_error(L, "invalid format (width or precision too long)"); |
851 | *(form++) = '%'; | 963 | *(form++) = '%'; |
852 | memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); | 964 | memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); |
853 | form += p - strfrmt + 1; | 965 | form += (p - strfrmt) + 1; |
854 | *form = '\0'; | 966 | *form = '\0'; |
855 | return p; | 967 | return p; |
856 | } | 968 | } |
@@ -891,23 +1003,25 @@ static int str_format (lua_State *L) { | |||
891 | strfrmt = scanformat(L, strfrmt, form); | 1003 | strfrmt = scanformat(L, strfrmt, form); |
892 | switch (*strfrmt++) { | 1004 | switch (*strfrmt++) { |
893 | case 'c': { | 1005 | case 'c': { |
894 | nb = sprintf(buff, form, (int)luaL_checkinteger(L, arg)); | 1006 | nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); |
895 | break; | 1007 | break; |
896 | } | 1008 | } |
897 | case 'd': case 'i': | 1009 | case 'd': case 'i': |
898 | case 'o': case 'u': case 'x': case 'X': { | 1010 | case 'o': case 'u': case 'x': case 'X': { |
899 | lua_Integer n = luaL_checkinteger(L, arg); | 1011 | lua_Integer n = luaL_checkinteger(L, arg); |
900 | addlenmod(form, LUA_INTEGER_FRMLEN); | 1012 | addlenmod(form, LUA_INTEGER_FRMLEN); |
901 | nb = sprintf(buff, form, n); | 1013 | nb = l_sprintf(buff, MAX_ITEM, form, n); |
902 | break; | 1014 | break; |
903 | } | 1015 | } |
904 | #if defined(LUA_USE_AFORMAT) | ||
905 | case 'a': case 'A': | 1016 | case 'a': case 'A': |
906 | #endif | 1017 | addlenmod(form, LUA_NUMBER_FRMLEN); |
1018 | nb = lua_number2strx(L, buff, MAX_ITEM, form, | ||
1019 | luaL_checknumber(L, arg)); | ||
1020 | break; | ||
907 | case 'e': case 'E': case 'f': | 1021 | case 'e': case 'E': case 'f': |
908 | case 'g': case 'G': { | 1022 | case 'g': case 'G': { |
909 | addlenmod(form, LUA_NUMBER_FRMLEN); | 1023 | addlenmod(form, LUA_NUMBER_FRMLEN); |
910 | nb = sprintf(buff, form, luaL_checknumber(L, arg)); | 1024 | nb = l_sprintf(buff, MAX_ITEM, form, luaL_checknumber(L, arg)); |
911 | break; | 1025 | break; |
912 | } | 1026 | } |
913 | case 'q': { | 1027 | case 'q': { |
@@ -917,23 +1031,27 @@ static int str_format (lua_State *L) { | |||
917 | case 's': { | 1031 | case 's': { |
918 | size_t l; | 1032 | size_t l; |
919 | const char *s = luaL_tolstring(L, arg, &l); | 1033 | const char *s = luaL_tolstring(L, arg, &l); |
920 | if (!strchr(form, '.') && l >= 100) { | 1034 | if (form[2] == '\0') /* no modifiers? */ |
921 | /* no precision and string is too long to be formatted; | 1035 | luaL_addvalue(&b); /* keep entire string */ |
922 | keep original string */ | ||
923 | luaL_addvalue(&b); | ||
924 | break; | ||
925 | } | ||
926 | else { | 1036 | else { |
927 | nb = sprintf(buff, form, s); | 1037 | luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); |
928 | lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ | 1038 | if (!strchr(form, '.') && l >= 100) { |
929 | break; | 1039 | /* no precision and string is too long to be formatted */ |
1040 | luaL_addvalue(&b); /* keep entire string */ | ||
1041 | } | ||
1042 | else { /* format the string into 'buff' */ | ||
1043 | nb = l_sprintf(buff, MAX_ITEM, form, s); | ||
1044 | lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ | ||
1045 | } | ||
930 | } | 1046 | } |
1047 | break; | ||
931 | } | 1048 | } |
932 | default: { /* also treat cases 'pnLlh' */ | 1049 | default: { /* also treat cases 'pnLlh' */ |
933 | return luaL_error(L, "invalid option '%%%c' to 'format'", | 1050 | return luaL_error(L, "invalid option '%%%c' to 'format'", |
934 | *(strfrmt - 1)); | 1051 | *(strfrmt - 1)); |
935 | } | 1052 | } |
936 | } | 1053 | } |
1054 | lua_assert(nb < MAX_ITEM); | ||
937 | luaL_addsize(&b, nb); | 1055 | luaL_addsize(&b, nb); |
938 | } | 1056 | } |
939 | } | 1057 | } |
@@ -1225,8 +1343,13 @@ static int str_pack (lua_State *L) { | |||
1225 | case Kchar: { /* fixed-size string */ | 1343 | case Kchar: { /* fixed-size string */ |
1226 | size_t len; | 1344 | size_t len; |
1227 | const char *s = luaL_checklstring(L, arg, &len); | 1345 | const char *s = luaL_checklstring(L, arg, &len); |
1228 | luaL_argcheck(L, len == (size_t)size, arg, "wrong length"); | 1346 | if ((size_t)size <= len) /* string larger than (or equal to) needed? */ |
1229 | luaL_addlstring(&b, s, size); | 1347 | luaL_addlstring(&b, s, size); /* truncate string to asked size */ |
1348 | else { /* string smaller than needed */ | ||
1349 | luaL_addlstring(&b, s, len); /* add it all */ | ||
1350 | while (len++ < (size_t)size) /* pad extra space */ | ||
1351 | luaL_addchar(&b, LUA_PACKPADBYTE); | ||
1352 | } | ||
1230 | break; | 1353 | break; |
1231 | } | 1354 | } |
1232 | case Kstring: { /* strings with length count */ | 1355 | case Kstring: { /* strings with length count */ |
@@ -1249,7 +1372,7 @@ static int str_pack (lua_State *L) { | |||
1249 | totalsize += len + 1; | 1372 | totalsize += len + 1; |
1250 | break; | 1373 | break; |
1251 | } | 1374 | } |
1252 | case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* go through */ | 1375 | case Kpadding: luaL_addchar(&b, LUA_PACKPADBYTE); /* FALLTHROUGH */ |
1253 | case Kpaddalign: case Knop: | 1376 | case Kpaddalign: case Knop: |
1254 | arg--; /* undo increment */ | 1377 | arg--; /* undo increment */ |
1255 | break; | 1378 | break; |
@@ -1276,7 +1399,7 @@ static int str_packsize (lua_State *L) { | |||
1276 | case Kstring: /* strings with length count */ | 1399 | case Kstring: /* strings with length count */ |
1277 | case Kzstr: /* zero-terminated string */ | 1400 | case Kzstr: /* zero-terminated string */ |
1278 | luaL_argerror(L, 1, "variable-length format"); | 1401 | luaL_argerror(L, 1, "variable-length format"); |
1279 | break; | 1402 | /* call never return, but to avoid warnings: *//* FALLTHROUGH */ |
1280 | default: break; | 1403 | default: break; |
1281 | } | 1404 | } |
1282 | } | 1405 | } |