1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Avoid unwelcomed side effects on the input operands in the OP_Concat

operator.  Fix for ticket [3be1295b264be2fac49b681]

FossilOrigin-Name: 713caa382cf7ddef872e510a76a5fca40be1a8d8876ce2f91b632bb0810a6630
This commit is contained in:
drh
2019-05-01 15:32:40 +00:00
parent c97001fd55
commit 8a7e11fb78
4 changed files with 42 additions and 22 deletions

View File

@@ -195,14 +195,6 @@ int sqlite3_found_count = 0;
}
#endif
/*
** Convert the given register into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
#define Stringify(P, enc) \
if(((P)->flags&(MEM_Str|MEM_Blob))==0 && sqlite3VdbeMemStringify(P,enc,0)) \
{ goto no_mem; }
/*
** An ephemeral string value (signified by the MEM_Ephem flag) contains
** a pointer to a dynamically allocated string where some other entity
@@ -1463,19 +1455,34 @@ case OP_ResultRow: {
** to avoid a memcpy().
*/
case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
i64 nByte;
i64 nByte; /* Total size of the output string or blob */
u16 flags1; /* Initial flags for P1 */
u16 flags2; /* Initial flags for P2 */
pIn1 = &aMem[pOp->p1];
pIn2 = &aMem[pOp->p2];
pOut = &aMem[pOp->p3];
testcase( pIn1==pIn2 );
testcase( pOut==pIn2 );
assert( pIn1!=pOut );
if( (pIn1->flags | pIn2->flags) & MEM_Null ){
flags1 = pIn1->flags;
testcase( flags1 & MEM_Null );
testcase( pIn2->flags & MEM_Null );
if( (flags1 | pIn2->flags) & MEM_Null ){
sqlite3VdbeMemSetNull(pOut);
break;
}
if( ExpandBlob(pIn1) || ExpandBlob(pIn2) ) goto no_mem;
Stringify(pIn1, encoding);
Stringify(pIn2, encoding);
if( (flags1 & (MEM_Str|MEM_Blob))==0 ){
if( sqlite3VdbeMemStringify(pIn1,encoding,0) ) goto no_mem;
}else if( (flags1 & MEM_Zero)!=0 ){
if( sqlite3VdbeMemExpandBlob(pIn1) ) goto no_mem;
}
flags2 = pIn2->flags;
if( (flags2 & (MEM_Str|MEM_Blob))==0 ){
if( sqlite3VdbeMemStringify(pIn2,encoding,0) ) goto no_mem;
}else if( (flags2 & MEM_Zero)!=0 ){
if( sqlite3VdbeMemExpandBlob(pIn2) ) goto no_mem;
}
nByte = pIn1->n + pIn2->n;
if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
@@ -1486,8 +1493,12 @@ case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */
MemSetTypeFlag(pOut, MEM_Str);
if( pOut!=pIn2 ){
memcpy(pOut->z, pIn2->z, pIn2->n);
assert( (pIn2->flags & MEM_Dyn) == (flags2 & MEM_Dyn) );
pIn2->flags = flags2;
}
memcpy(&pOut->z[pIn2->n], pIn1->z, pIn1->n);
assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
pIn1->flags = flags1;
pOut->z[nByte]=0;
pOut->z[nByte+1] = 0;
pOut->flags |= MEM_Term;