diff --git a/src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs b/src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs index 2a57c02af2..4c0f5dab67 100644 --- a/src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs +++ b/src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs @@ -415,33 +415,49 @@ public override void EnterMultiplicative(JavascriptParser.MultiplicativeContext public override void EnterShift(JavascriptParser.ShiftContext context) { - CompileBinary(context, context.additive, additiveContext => + EnterAdditive(context.additive(0)); + + if (context.children.Count == 1) // if we don't have a shift token { - EnterAdditive(additiveContext); + return; + } - if (context.children.Count > 1) // if we have a shift token - { - compiler.Emit(OpCodes.Conv_I8); // cast to long (truncate) - } - }, terminalNode => + compiler.Emit(OpCodes.Conv_I8); // cast to long (truncate) + int argIndex = 1; + + for (int i = 1; i < context.children.Count; i += 2) { - if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHL) - { - compiler.PushOpWithConvert(OpCodes.Shl); - } - else if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHR) - { - compiler.PushOpWithConvert(OpCodes.Shr); - } - else if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHU) + if (context.children[i] is ITerminalNode terminalNode) { - compiler.PushOpWithConvert(OpCodes.Shr_Un); + EnterAdditive(context.additive(argIndex++)); + compiler.Emit(OpCodes.Conv_I4); // cast to int (truncate) + + // mask off 63 to prevent overflow (fixes issue on x86 .NET Framework, #1034) + compiler.Emit(OpCodes.Ldc_I4, 0x3F); + compiler.Emit(OpCodes.And); + + if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHL) + { + compiler.PushOpWithConvert(OpCodes.Shl); + } + else if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHR) + { + compiler.PushOpWithConvert(OpCodes.Shr); + } + else if (terminalNode.Symbol.Type == JavascriptParser.AT_BIT_SHU) + { + compiler.PushOpWithConvert(OpCodes.Shr_Un); + } + else + { + throw new ParseException("Unknown shift token", context.Start.StartIndex); + } } else { - throw new ParseException("Unknown shift token", context.Start.StartIndex); + throw new ParseException("Unexpected child", context.Start.StartIndex); } - }); + } } public override void EnterRelational(JavascriptParser.RelationalContext context)