瀏覽代碼

Merge pull request #7357 from ghalliday/issue13590

HPCC-13590 Fix IF() row accessing row that has been destroyed

Reviewed-By: Jamie Noss <james.noss@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 10 年之前
父節點
當前提交
b02ead218d

+ 3 - 0
ecl/hqlcpp/hqlcppds.cpp

@@ -4405,6 +4405,9 @@ void HqlCppTranslator::buildRowAssign(BuildCtx & ctx, IReferenceSelector * targe
     case no_null:
         doBuildRowAssignNullRow(ctx, target, expr);
         return;
+    case no_nofold:
+        buildRowAssign(ctx, target, expr->queryChild(0));
+        return;
     case no_serialize:
         {
             IHqlExpression * deserialized = expr->queryChild(0);

+ 7 - 0
ecl/hqlcpp/hqlcset.cpp

@@ -1880,6 +1880,13 @@ void LinkedDatasetBuilderBase::buildFinish(BuildCtx & ctx, CHqlBoundExpr & bound
     bound.count.setown(createQuoted(s.str(), LINK(unsignedType)));
     s.clear().append(instanceName).append(".queryrows()");
     bound.expr.setown(createQuoted(s.str(), makeReferenceModifier(dataset->getType())));
+    if (!ctx.isOuterContext() && ctx.queryMatchExpr(queryConditionalRowMarker()))
+    {
+        //If processing a conditional row, create a dataset object (at the outer-most) level
+        //and assign to that, to ensure the dataset doesn't go out of scope.
+        OwnedHqlExpr translated = bound.getTranslatedExpr();
+        translator.buildTempExpr(ctx, translated, bound);
+    }
 }
 
 bool LinkedDatasetBuilderBase::buildLinkRow(BuildCtx & ctx, BoundRow * sourceRow)

+ 25 - 0
ecl/hqlcpp/hqlstmt.cpp

@@ -616,6 +616,31 @@ bool BuildCtx::hasAssociation(HqlExprAssociation & search, bool unconditional)
 }
 
 
+bool BuildCtx::isOuterContext() const
+{
+    HqlStmts * searchStmts = curStmts;
+    loop
+    {
+        HqlStmt * owner = searchStmts->owner;
+        if (!owner)
+            return true;
+
+        switch (owner->getStmt())
+        {
+        case quote_compound_stmt:
+        case quote_compoundopt_stmt:
+        case indirect_stmt:
+            return true;
+        case group_stmt:
+            break;
+        default:
+            return false;
+        }
+
+        searchStmts = owner->queryContainer();
+    }
+}
+
 HqlExprAssociation * BuildCtx::queryAssociation(IHqlExpression * search, AssocKind kind, HqlExprCopyArray * selectors)
 {
     HqlStmts * searchStmts = curStmts;

+ 1 - 0
ecl/hqlcpp/hqlstmt.hpp

@@ -135,6 +135,7 @@ public:
     HqlExprAssociation *        queryMatchExpr(IHqlExpression * expr);
     bool                        getMatchExpr(IHqlExpression * expr, CHqlBoundExpr & bound);
     IHqlExpression *            getTempDeclare(ITypeInfo * type, IHqlExpression * value);
+    bool                        isOuterContext() const;
     void                        needFunction(IFunctionInfo & helper);
     void                        needFunction(IAtom * name);
     void                        removeAssociation(HqlExprAssociation * search);

+ 7 - 0
roxie/roxiemem/roxiemem.cpp

@@ -27,6 +27,7 @@
 
 #ifdef _DEBUG
 #define _CLEAR_ALLOCATED_ROW
+#define _CLEAR_FREED_ROW
 //#define _CLEAR_ALLOCATED_HUGE_ROW
 #endif
 
@@ -1250,6 +1251,9 @@ public:
                 allocatorCache->onDestroy(id & MAX_ACTIVITY_ID, ptr + chunkHeaderSize);
             }
 
+#ifdef _CLEAR_FREED_ROW
+            memset((void *)_ptr, 0xdd, chunkCapacity);
+#endif
             inlineReleasePointer(ptr);
         }
     }
@@ -1482,6 +1486,9 @@ public:
             if (rowCount & ROWCOUNT_DESTRUCTOR_FLAG)
                 allocatorCache->onDestroy(sharedAllocatorId & MAX_ACTIVITY_ID, ptr + chunkHeaderSize);
 
+#ifdef _CLEAR_FREED_ROW
+            memset((void *)_ptr, 0xdd, chunkCapacity);
+#endif
             inlineReleasePointer(ptr);
         }
     }

+ 43 - 0
testing/regress/ecl/issue13590.ecl

@@ -0,0 +1,43 @@
+/*##############################################################################
+
+    HPCC SYSTEMS software Copyright (C) 2015 HPCC Systems.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+############################################################################## */
+
+
+idRec := { STRING id; };
+
+one := '1' : stored('one');
+two := '2' : stored('two');
+three := '3' : stored('three');
+
+ids(STRING base) := NOFOLD(DATASET([one+base,two+base], idRec));
+
+rRec := RECORD
+    STRING x;
+    DATASET(idRec) y;
+END;
+
+ds := DATASET(['92','67','56','23'], idRec);
+
+rRec t(idRec l) := TRANSFORM
+    y1 := DATASET([three], idRec);
+    ids := ids(l.id);
+    y2 := NOFOLD(IF(ids[1].id >= '0', ids[1], ids[2]));
+    y3 := NOFOLD(IF(l.id > '60', y2, y1[1]));
+    SELF.x := l.id;
+    SELF.y := y1 & y3;
+END;
+
+OUTPUT(PROJECT(ds, t(LEFT)));

+ 6 - 0
testing/regress/ecl/key/issue13590.xml

@@ -0,0 +1,6 @@
+<Dataset name='Result 1'>
+ <Row><x>92</x><y><Row><id>3</id></Row><Row><id>192</id></Row></y></Row>
+ <Row><x>67</x><y><Row><id>3</id></Row><Row><id>167</id></Row></y></Row>
+ <Row><x>56</x><y><Row><id>3</id></Row><Row><id>3</id></Row></y></Row>
+ <Row><x>23</x><y><Row><id>3</id></Row><Row><id>3</id></Row></y></Row>
+</Dataset>