Browse Source

HPCC-20658 Fix memory corruption clearing rows containing IFBLOCKs

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 6 years ago
parent
commit
2f584b26de
2 changed files with 29 additions and 0 deletions
  1. 28 0
      ecl/hqlcpp/hqltcppc.cpp
  2. 1 0
      ecl/hqlcpp/hqltcppc.ipp

+ 28 - 0
ecl/hqlcpp/hqltcppc.cpp

@@ -1226,6 +1226,34 @@ void CIfBlockInfo::buildDeserialize(HqlCppTranslator & translator, BuildCtx & ct
     ctx.associateExpr(sizeOfIfBlock, cachedSize.expr);
     ctx.associateExpr(sizeOfIfBlock, cachedSize.expr);
 }
 }
 
 
+void CIfBlockInfo::buildClear(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, int direction)
+{
+    //MORE: This should really associate offset of the ifblock with the offset of its first child as well.
+    CHqlBoundExpr boundOffset;
+    buildOffset(translator, ctx, selector, boundOffset);
+
+    //NB: Sizeof(ifblock) has an unusual representation...
+    OwnedHqlExpr sizeOfIfBlock = createValue(no_sizeof, makeIntType(4,false), createSelectExpr(LINK(selector->queryExpr()), LINK(column)));
+    CHqlBoundTarget cachedSize;
+    cachedSize.expr.setown(ctx.getTempDeclare(sizetType, queryZero()));
+
+    //MORE: Should also conditionally set a variable to the size of the ifblock to simplify subsequent generated code
+    OwnedHqlExpr cond = selector->queryRootRow()->bindToRow(condition, queryRootSelf());
+    CHqlBoundExpr bound;
+    translator.buildSimpleExpr(ctx, cond, bound);
+    BuildCtx condctx(ctx);
+    condctx.addFilter(bound.expr);
+
+    //MORE: This test could be avoided if the first child is *actually* variable length
+    ensureTargetAvailable(translator, condctx, selector, CContainerInfo::getTotalMinimumSize());
+    CContainerInfo::buildClear(translator, condctx, selector, direction);
+
+    //Avoid recalculating the size outside of the ifblock()
+    translator.buildExprAssign(condctx, cachedSize, sizeOfIfBlock);
+
+    ctx.associateExpr(sizeOfIfBlock, cachedSize.expr);
+}
+
 void CIfBlockInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
 void CIfBlockInfo::buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm)
 {
 {
     OwnedHqlExpr cond = selector->queryRootRow()->bindToRow(condition, queryRootSelf());
     OwnedHqlExpr cond = selector->queryRootRow()->bindToRow(condition, queryRootSelf());

+ 1 - 0
ecl/hqlcpp/hqltcppc.ipp

@@ -243,6 +243,7 @@ public:
 
 
 //AColumnInfo
 //AColumnInfo
     virtual void buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target);
     virtual void buildAssign(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, const CHqlBoundTarget & target);
+    virtual void buildClear(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, int direction);
     virtual void buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound);
     virtual void buildExpr(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, CHqlBoundExpr & bound);
     virtual void buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm);
     virtual void buildDeserialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm);
     virtual void buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm);
     virtual void buildSerialize(HqlCppTranslator & translator, BuildCtx & ctx, IReferenceSelector * selector, IHqlExpression * helper, IAtom * serializeForm);