From: Francis De Brabandere <francisdb@gmail.com> Native cscript accepts &O0, &O17, &O177777, etc. as octal integer literals. Wine was emitting err 1002 (syntax error) for any &O prefix because the lexer only recognised &H. Add an oct_to_int helper and parse_oct_literal mirroring parse_hex_literal, allowing up to 32-bit values; overflow checks use an ULONGLONG accumulator since 11-digit octal can exceed 32 bits. --- dlls/vbscript/lex.c | 35 +++++++++++++++++++++++++++++++++++ dlls/vbscript/tests/lang.vbs | 26 +++++++++++++------------- 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 81cc67e037b..bd6d97bf6d7 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -394,6 +394,39 @@ static int parse_hex_literal(parser_ctx_t *ctx, LONG *ret) return tInt; } +static int oct_to_int(WCHAR c) +{ + if('0' <= c && c <= '7') + return c-'0'; + return -1; +} + +static int parse_oct_literal(parser_ctx_t *ctx, LONG *ret) +{ + ULONGLONG l = 0; + int d; + + /* Skip leading zeros — Windows allows any number of them. */ + while(ctx->ptr[1] == '0') + ctx->ptr++; + + while((d = oct_to_int(*++ctx->ptr)) != -1) { + l = l*8 + d; + if(l > 0xFFFFFFFFULL) { + WARN("overflow in oct literal\n"); + return 0; + } + } + + if(*ctx->ptr == '&') { + ctx->ptr++; + *ret = (LONG)l; + }else { + *ret = l == (UINT16)l ? (INT16)l : (LONG)l; + } + return tInt; +} + static void skip_spaces(parser_ctx_t *ctx) { while(*ctx->ptr == ' ' || *ctx->ptr == '\t' || *ctx->ptr == '\v' || *ctx->ptr == '\f') @@ -537,6 +570,8 @@ static int parse_next_token(void *lval, unsigned *loc, parser_ctx_t *ctx) case '&': if((*++ctx->ptr == 'h' || *ctx->ptr == 'H') && hex_to_int(ctx->ptr[1]) != -1) return parse_hex_literal(ctx, lval); + if((*ctx->ptr == 'o' || *ctx->ptr == 'O') && oct_to_int(ctx->ptr[1]) != -1) + return parse_oct_literal(ctx, lval); return '&'; case '=': switch(*++ctx->ptr) { diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 0abbe10d2e7..4923f8ae574 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -78,19 +78,19 @@ sub testOctalLiterals() Dim oct on error resume next - Err.Clear : oct = Eval("&O0") : todo_wine_ok Err.number = 0 and oct = 0, "&O0 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O17") : todo_wine_ok Err.number = 0 and oct = 15, "&O17 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O77") : todo_wine_ok Err.number = 0 and oct = 63, "&O77 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O777") : todo_wine_ok Err.number = 0 and oct = 511, "&O777 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O177777") : todo_wine_ok Err.number = 0 and oct = -1, "&O177777 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O200000") : todo_wine_ok Err.number = 0 and oct = 65536, "&O200000 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O17777777777") : todo_wine_ok Err.number = 0 and oct = 2147483647, "&O17777777777 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O37777777777") : todo_wine_ok Err.number = 0 and oct = -1, "&O37777777777 oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O17&") : todo_wine_ok Err.number = 0 and oct = 15, "&O17& oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O177777&") : todo_wine_ok Err.number = 0 and oct = 65535, "&O177777& oct=" & oct & " err=" & Err.number - Err.Clear : oct = Eval("&O77") : todo_wine_ok Err.number = 0 and getVT(oct) = "VT_I2*", "getVT(&O77) = " & getVT(oct) - Err.Clear : oct = Eval("&O200000") : todo_wine_ok Err.number = 0 and getVT(oct) = "VT_I4*", "getVT(&O200000) = " & getVT(oct) - Err.Clear : oct = Eval("&O177777&") : todo_wine_ok Err.number = 0 and getVT(oct) = "VT_I4*", "getVT(&O177777&) = " & getVT(oct) + Err.Clear : oct = Eval("&O0") : call ok(Err.number = 0 and oct = 0, "&O0 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O17") : call ok(Err.number = 0 and oct = 15, "&O17 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O77") : call ok(Err.number = 0 and oct = 63, "&O77 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O777") : call ok(Err.number = 0 and oct = 511, "&O777 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O177777") : call ok(Err.number = 0 and oct = -1, "&O177777 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O200000") : call ok(Err.number = 0 and oct = 65536, "&O200000 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O17777777777") : call ok(Err.number = 0 and oct = 2147483647, "&O17777777777 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O37777777777") : call ok(Err.number = 0 and oct = -1, "&O37777777777 oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O17&") : call ok(Err.number = 0 and oct = 15, "&O17& oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O177777&") : call ok(Err.number = 0 and oct = 65535, "&O177777& oct=" & oct & " err=" & Err.number) + Err.Clear : oct = Eval("&O77") : call ok(Err.number = 0 and getVT(oct) = "VT_I2*", "getVT(&O77) = " & getVT(oct)) + Err.Clear : oct = Eval("&O200000") : call ok(Err.number = 0 and getVT(oct) = "VT_I4*", "getVT(&O200000) = " & getVT(oct)) + Err.Clear : oct = Eval("&O177777&") : call ok(Err.number = 0 and getVT(oct) = "VT_I4*", "getVT(&O177777&) = " & getVT(oct)) Err.Clear : oct = Eval("&O8") : call ok(Err.number = 1002, "&O8 should be syntax error, got err=" & Err.number) end sub call testOctalLiterals() -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10900