Skip to content

Commit ac0b41a

Browse files
authored
[C++] check for not wrapped state in decodeLength() when precedence checks are enabled (#1046)
1 parent a209a2f commit ac0b41a

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/cpp/CppGenerator.java

+40-1
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,18 @@ private static void generateAccessOrderException(
536536
.append(fieldPrecedenceModel.generatedRepresentationClassName()).append(".\");\n");
537537
}
538538

539+
private static void generateAccessOrderException(
540+
final StringBuilder sb,
541+
final String indent,
542+
final String action)
543+
{
544+
sb.append(indent).append("throw AccessOrderError(")
545+
.append("std::string(\"Illegal access. \") + \n")
546+
.append(indent).append(INDENT)
547+
.append("\"Cannot call \\\"").append(action)
548+
.append("()\\\" in state: \" + codecStateName(codecState()));\n");
549+
}
550+
539551
private static void generateAccessOrderListenerMethodForNextGroupElement(
540552
final StringBuilder sb,
541553
final FieldPrecedenceModel fieldPrecedenceModel,
@@ -3027,6 +3039,7 @@ private CharSequence generateMessageFlyweightCode(
30273039

30283040
" SBE_NODISCARD std::uint64_t decodeLength() const\n" +
30293041
" {\n" +
3042+
"%22$s" +
30303043
" %10$s skipper(m_buffer, m_offset, m_bufferLength, m_actingBlockLength, m_actingVersion);\n" +
30313044
" skipper.skip();\n" +
30323045
" return skipper.encodedLength();\n" +
@@ -3071,7 +3084,8 @@ private CharSequence generateMessageFlyweightCode(
30713084
generateCodecStateTransitionForWrappingLatestVersion(fieldPrecedenceModel),
30723085
generateOnWrappedListener(fieldPrecedenceModel),
30733086
generateCodecStateTransitionForWrapping(fieldPrecedenceModel),
3074-
generateHiddenCopyConstructor(" ", className));
3087+
generateHiddenCopyConstructor(" ", className),
3088+
generateCheckForNotWrappedState("decodeLength", fieldPrecedenceModel));
30753089
}
30763090

30773091
private CharSequence generateAccessOrderErrorType(final FieldPrecedenceModel fieldPrecedenceModel)
@@ -3311,6 +3325,31 @@ private CharSequence generateCodecStateTransitionForWrapping(final FieldPreceden
33113325
return generateAccessOrderListenerCall(fieldPrecedenceModel, TWO_INDENT, "onWrapped", "actingVersion");
33123326
}
33133327

3328+
private CharSequence generateCheckForNotWrappedState(
3329+
final String action,
3330+
final FieldPrecedenceModel fieldPrecedenceModel)
3331+
{
3332+
if (null == fieldPrecedenceModel)
3333+
{
3334+
return "";
3335+
}
3336+
3337+
final StringBuilder sb = new StringBuilder();
3338+
sb.append("#if defined(").append(precedenceChecksFlagName).append(")\n")
3339+
.append(TWO_INDENT)
3340+
.append("if (codecState() == ")
3341+
.append(qualifiedStateCase(fieldPrecedenceModel.notWrappedState()))
3342+
.append(")\n")
3343+
.append(TWO_INDENT).append("{\n");
3344+
3345+
generateAccessOrderException(sb, THREE_INDENT, action);
3346+
3347+
sb.append(TWO_INDENT).append("}\n")
3348+
.append("#endif\n");
3349+
3350+
return sb;
3351+
}
3352+
33143353
private CharSequence generateCodecStateTransitionForWrappingLatestVersion(
33153354
final FieldPrecedenceModel fieldPrecedenceModel
33163355
)

sbe-tool/src/test/cpp/FieldAccessOrderCheckTest.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -5048,3 +5048,43 @@ TEST_F(FieldAccessOrderCheckTest, worksWithInsertionOperator)
50485048
EXPECT_EQ(decoder.getBAsString(), "abc");
50495049
EXPECT_EQ(decoder.getCAsString(), "def");
50505050
}
5051+
5052+
TEST_F(FieldAccessOrderCheckTest, shouldThrowExceptionWhenNotWrapped)
5053+
{
5054+
MultipleVarLength encoder;
5055+
encoder.wrapForEncode(m_buffer, OFFSET, BUFFER_LEN);
5056+
encoder.a(42);
5057+
encoder.putB("abc");
5058+
encoder.putC("def");
5059+
encoder.checkEncodingIsComplete();
5060+
5061+
MultipleVarLength decoder;
5062+
5063+
EXPECT_THROW(
5064+
{
5065+
try
5066+
{
5067+
decoder.decodeLength();
5068+
}
5069+
catch (const std::exception &e)
5070+
{
5071+
EXPECT_THAT(
5072+
e.what(),
5073+
HasSubstr("Illegal access. Cannot call \"decodeLength()\" in state: NOT_WRAPPED")
5074+
);
5075+
throw;
5076+
}
5077+
},
5078+
std::logic_error
5079+
);
5080+
5081+
decoder.wrapForDecode(
5082+
m_buffer,
5083+
OFFSET,
5084+
MultipleVarLength::sbeBlockLength(),
5085+
MultipleVarLength::sbeSchemaVersion(),
5086+
BUFFER_LEN
5087+
);
5088+
5089+
decoder.decodeLength();
5090+
}

0 commit comments

Comments
 (0)