diff --git a/be/src/exprs/aggregate-functions.cc b/be/src/exprs/aggregate-functions.cc index 05f9c561d..e514d902c 100644 --- a/be/src/exprs/aggregate-functions.cc +++ b/be/src/exprs/aggregate-functions.cc @@ -127,14 +127,14 @@ namespace impala { // 'dst' will be set to a null string. This allows execution to continue until the // next time GetQueryStatus() is called (see IMPALA-2756). static void AllocBuffer(FunctionContext* ctx, StringVal* dst, size_t buf_len) { - DCHECK_GT(buf_len, 0); uint8_t* ptr = ctx->Allocate(buf_len); - if (UNLIKELY(ptr == NULL)) { + if (UNLIKELY(ptr == NULL && buf_len != 0)) { DCHECK(!ctx->impl()->state()->GetQueryStatus().ok()); *dst = StringVal::null(); } else { *dst = StringVal(ptr, buf_len); - memset(ptr, 0, buf_len); + // Avoid memset() with NULL ptr as it's undefined. + if (LIKELY(ptr != NULL)) memset(ptr, 0, buf_len); } } @@ -142,14 +142,14 @@ static void AllocBuffer(FunctionContext* ctx, StringVal* dst, size_t buf_len) { // 'buf_len' bytes and copies the content of StringVal 'src' into it. // If allocation fails, 'dst' will be set to a null string. static void CopyStringVal(FunctionContext* ctx, const StringVal& src, StringVal* dst) { - DCHECK_GT(src.len, 0); uint8_t* copy = ctx->Allocate(src.len); - if (UNLIKELY(copy == NULL)) { + if (UNLIKELY(copy == NULL && src.len != 0)) { DCHECK(!ctx->impl()->state()->GetQueryStatus().ok()); *dst = StringVal::null(); } else { *dst = StringVal(copy, src.len); - memcpy(dst->ptr, src.ptr, src.len); + // Avoid memcpy() to NULL ptr as it's undefined. + if (LIKELY(dst->ptr != NULL)) memcpy(dst->ptr, src.ptr, src.len); } } diff --git a/testdata/workloads/functional-query/queries/QueryTest/aggregation.test b/testdata/workloads/functional-query/queries/QueryTest/aggregation.test index f8a3fbea1..5389b04f3 100644 --- a/testdata/workloads/functional-query/queries/QueryTest/aggregation.test +++ b/testdata/workloads/functional-query/queries/QueryTest/aggregation.test @@ -154,6 +154,15 @@ from alltypesagg where day is not null bigint, string, string, string, string ==== ---- QUERY +# Test for IMPALA-3018. Verify update() function of min() handles +# zero-length string correctly. +select min(str) from (values ('aaa' as str), ('')) as tmp +---- RESULTS +'' +---- TYPES +String +==== +---- QUERY # grouping by different data types, with NULLs select tinyint_col, count(*) from alltypesagg where day is not null group by 1 order by 1 ---- RESULTS