Skip to content

Commit

Permalink
Expressions.JS: Bitwise left shift bugfixes, apache#1034 (apache#1048)
Browse files Browse the repository at this point in the history
* Mask off 63 from shift operand, apache#1034

* Use 32-bit operand for shift operations, apache#1034
  • Loading branch information
paulirwin authored Nov 26, 2024
1 parent 6d62a57 commit e9c865c
Showing 1 changed file with 35 additions and 19 deletions.
54 changes: 35 additions & 19 deletions src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit e9c865c

Please sign in to comment.