Skip to content

Commit

Permalink
[#641] Disallow most of the expressions in offsets
Browse files Browse the repository at this point in the history
  • Loading branch information
Mi-La committed Aug 16, 2024
1 parent 009d16a commit 8096ba7
Show file tree
Hide file tree
Showing 63 changed files with 1,135 additions and 476 deletions.
6 changes: 0 additions & 6 deletions compiler/core/src/zserio/ast/Field.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,6 @@ private void checkOffsetExpression()
"' is not an unsigned fixed sized integer type!");
}

if (offsetExpr.containsFunctionCallOutOfArray())
throw new ParserException(offsetExpr, "Function call cannot be used for offset setting!");

if (offsetExpr.containsTernaryOperatorOutOfArray())
throw new ParserException(offsetExpr, "Ternary operator cannot be used for offset setting!");

if (offsetExpr.op2() == null)
{
final AstNode symbolObject = offsetExpr.getExprSymbolObject();
Expand Down
310 changes: 307 additions & 3 deletions compiler/core/src/zserio/ast/ZserioParseTreeChecker.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.Token;

import zserio.antlr.ZserioParser;
import zserio.antlr.ZserioParserBaseVisitor;
import zserio.tools.WarningsConfig;
Expand Down Expand Up @@ -61,10 +64,10 @@ public Void visitStructureFieldDefinition(ZserioParser.StructureFieldDefinitionC
public Void visitFieldOffset(ZserioParser.FieldOffsetContext ctx)
{
// index expression in offsets is allowed if we are in array which is not implicit
if (isInArrayField && !isInImplicitArrayField)
isIndexAllowed = true;
isInOffsetExpression = true;
visitChildren(ctx);
isIndexAllowed = false;
isInOffsetExpression = false;
wasIndexUsedInOffsetExpression = false;

return null;
}
Expand Down Expand Up @@ -143,6 +146,273 @@ public Void visitSqlTableFieldDefinition(ZserioParser.SqlTableFieldDefinitionCon
return null;
}

@Override
public Void visitParenthesizedExpression(ZserioParser.ParenthesizedExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(ctx, ctx.getStart(), "Parenthesis are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitFunctionCallExpression(ZserioParser.FunctionCallExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.LPAREN().getSymbol(), "Function call is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitArrayExpression(ZserioParser.ArrayExpressionContext ctx)
{
if (isInOffsetArrayExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Array expression is not allowed in offset array expressions!");
}

visit(ctx.expression(0));

if (isInOffsetExpression)
{
if (isInArrayField && !isInImplicitArrayField)
isIndexAllowed = true;
isInOffsetArrayExpression = true;
}

visit(ctx.expression(1));

if (isInOffsetExpression)
{
isIndexAllowed = false;
isInOffsetArrayExpression = false;
}

return null;
}

@Override
public Void visitDotExpression(ZserioParser.DotExpressionContext ctx)
{
if (isInOffsetArrayExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Dot expression is not allowed in offset array expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitIsSetExpression(ZserioParser.IsSetExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Operator isset is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitLengthofExpression(ZserioParser.LengthofExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Operator lengthof is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitValueofExpression(ZserioParser.ValueofExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Operator valueof is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitNumbitsExpression(ZserioParser.NumbitsExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Operator numbits is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitUnaryExpression(ZserioParser.UnaryExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Unary operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitMultiplicativeExpression(ZserioParser.MultiplicativeExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Arithmetic operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitAdditiveExpression(ZserioParser.AdditiveExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Arithmetic operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitShiftExpression(ZserioParser.ShiftExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Shift operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitRelationalExpression(ZserioParser.RelationalExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Relational operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitEqualityExpression(ZserioParser.EqualityExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Relational operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitBitwiseAndExpression(ZserioParser.BitwiseAndExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Bitwise operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitBitwiseXorExpression(ZserioParser.BitwiseXorExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Bitwise operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitBitwiseOrExpression(ZserioParser.BitwiseOrExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Bitwise operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitLogicalAndExpression(ZserioParser.LogicalAndExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Logical operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitLogicalOrExpression(ZserioParser.LogicalOrExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Logical operators are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitTernaryExpression(ZserioParser.TernaryExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(
ctx, ctx.operator, "Ternary operator is not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitLiteralExpression(ZserioParser.LiteralExpressionContext ctx)
{
if (isInOffsetExpression)
{
throwForbiddenInOffsets(ctx, ctx.getStart(), "Literals are not allowed in offset expressions!");
}

return visitChildren(ctx);
}

@Override
public Void visitIndexExpression(ZserioParser.IndexExpressionContext ctx)
{
Expand All @@ -161,12 +431,28 @@ public Void visitIndexExpression(ZserioParser.IndexExpressionContext ctx)
}
}

if (isInOffsetExpression)
{
if (wasIndexUsedInOffsetExpression)
{
throw new ParserException(
ctx.getStart(), "Index operator can be used only once within an offset expression!");
}
wasIndexUsedInOffsetExpression = true;
}

return visitChildren(ctx);
}

@Override
public Void visitId(ZserioParser.IdContext ctx)
{
if (isInOffsetArrayExpression)
{
throwForbiddenInOffsets(
ctx, ctx.getStart(), "Identifiers are not allowed in offset array expressions!");
}

try
{
IdentifierValidator.validate(ctx.getText());
Expand Down Expand Up @@ -196,6 +482,21 @@ public Void visitTypeArgument(ZserioParser.TypeArgumentContext ctx)
return null;
}

private void throwForbiddenInOffsets(ParserRuleContext ctx, Token locationToken, String message)
{
if (isInOffsetArrayExpression)
{
final ParserStackedException exception = new ParserStackedException(
new AstLocation(ctx.getStart()), "Only @index is allowed in offset array expressions!");
exception.pushMessage(new AstLocation(locationToken), message);
throw exception;
}
else
{
throw new ParserException(locationToken, message);
}
}

private void checkUtf8Encoding(AstLocation location)
{
final byte[] fileContent = readFile(location);
Expand Down Expand Up @@ -262,6 +563,9 @@ private byte[] readFile(AstLocation location)
private boolean isInArrayField = false;
private boolean isInImplicitArrayField = false;
private boolean isIndexAllowed = false;
private boolean isInOffsetExpression = false;
private boolean isInOffsetArrayExpression = false;
private boolean wasIndexUsedInOffsetExpression = false;

/** Flag used to allow explicit keyword only for SQL tables. */
private boolean isInSqlTableField = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public void implicitArrayWithLength()
@Test
public void implicitArrayWithIndexedOffsets()
{
final String error = "implicit_array_with_indexed_offsets_error.zs:22:9: "
final String error = "implicit_array_with_indexed_offsets_error.zs:14:9: "
+ "Implicit arrays cannot have indexed offsets!";
assertTrue(zserioErrors.isPresent(error));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ offset:
implicit uint32 array[];
};

struct OffsetArrayWithoutIndexIsOk
{
string description;
uint32 offset[];
offset[0]:
implicit uint32 array[];
};

struct ImplicitArrayWithOffsetsError
{
uint32 offsets[];
Expand Down
Loading

0 comments on commit 8096ba7

Please sign in to comment.