Headline
CVE-2020-11656: SQLite: Check-in [b64674919f]
In SQLite through 3.31.1, the ALTER TABLE implementation has a use-after-free, as demonstrated by an ORDER BY clause that belongs to a compound SELECT statement.
Overview
Comment:
Do not suppress errors when resolving references in an ORDER BY clause belonging to a compound SELECT within a view or trigger within ALTER TABLE. Fix for ticket [a10a14e9b4ba2]. Also, in the event of a semantic error in an aggregate query, early-out the resetAccumulator() function to prevent problems due to incomplete or incorrect initialization of the AggInfo object. Fix for ticket [af4556bb5c285c08].
Downloads:
Tarball | ZIP archive | SQL archive
Timelines:
family | ancestors | descendants | both | branch-3.31
Files:
files | file ages | folders
SHA3-256:
b64674919f6736025b2066672a5cf5cb51a28bbac4c709b85a1a6163cc0d7971
User & Date:
drh on 2020-04-03 13:39:03
Other Links:
branch diff | manifest | tags
Context
2020-04-03
20:14
Restore an #if block inadvertently removed via check-in [9c77bfe41e]. (check-in: bf6bcfc16e user: mistachkin tags: branch-3.31)
13:39
Do not suppress errors when resolving references in an ORDER BY clause belonging to a compound SELECT within a view or trigger within ALTER TABLE. Fix for ticket [a10a14e9b4ba2]. Also, in the event of a semantic error in an aggregate query, early-out the resetAccumulator() function to prevent problems due to incomplete or incorrect initialization of the AggInfo object. Fix for ticket [af4556bb5c285c08]. (check-in: b64674919f user: drh tags: branch-3.31)
13:29
Fix a case when a pointer might be used after being freed in the ALTER TABLE code. Fix for [4722bdab08cb1]. (check-in: 52f800fa93 user: drh tags: branch-3.31)
13:19
In the event of a semantic error in an aggregate query, early-out the resetAccumulator() function to prevent problems due to incomplete or incorrect initialization of the AggInfo object. Fix for ticket [af4556bb5c285c08]. (check-in: 4a302b42c7 user: drh tags: trunk)
11:52
Do not suppress errors when resolving references in an ORDER BY clause belonging to a compound SELECT within a view or trigger within ALTER TABLE. Fix for ticket [a10a14e9b4ba2]. (check-in: 684293882c user: dan tags: trunk)
Changes
Modified src/resolve.c from [f0781c9e18] to [534927e6f4].
︙
︙
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; nc.ncFlags = NC_AllowAgg|NC_UEList; nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; db->suppressErr = 1; rc = sqlite3ResolveExprNames(&nc, pE); db->suppressErr = savedSuppErr; if( rc ) return 0;
/* Try to match the ORDER BY expression against an expression ** in the result set. Return an 1-based index of the matching ** result-set entry.
|
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
nc.pParse = pParse; nc.pSrcList = pSelect->pSrc; nc.uNC.pEList = pEList; nc.ncFlags = NC_AllowAgg|NC_UEList; nc.nErr = 0; db = pParse->db; savedSuppErr = db->suppressErr; if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1; rc = sqlite3ResolveExprNames(&nc, pE); db->suppressErr = savedSuppErr; if( rc ) return 0;
/* Try to match the ORDER BY expression against an expression ** in the result set. Return an 1-based index of the matching ** result-set entry.
︙
︙
Modified src/select.c from [3f7aecf64b] to [f57c72267d].
︙
︙
5348 5349 5350 5351 5352 5353 5354
5355 5356 5357 5358 5359 5360 5361
*/ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; int nReg = pAggInfo->nFunc + pAggInfo->nColumn; if( nReg==0 ) return;
#ifdef SQLITE_DEBUG /* Verify that all AggInfo registers are within the range specified by ** AggInfo.mnReg…AggInfo.mxReg */ assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); for(i=0; i<pAggInfo->nColumn; i++){ assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg );
5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362
*/ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pFunc; int nReg = pAggInfo->nFunc + pAggInfo->nColumn; if( nReg==0 ) return; if( pParse->nErr ) return; #ifdef SQLITE_DEBUG /* Verify that all AggInfo registers are within the range specified by ** AggInfo.mnReg…AggInfo.mxReg */ assert( nReg==pAggInfo->mxReg-pAggInfo->mnReg+1 ); for(i=0; i<pAggInfo->nColumn; i++){ assert( pAggInfo->aCol[i].iMem>=pAggInfo->mnReg && pAggInfo->aCol[i].iMem<=pAggInfo->mxReg );
︙
︙
Modified test/altertab.test from [2c41e347c0] to [523ba6368e].
︙
︙
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
}
#------------------------------------------------------------------------- reset_db do_execsql_test 18.1.0 { CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)) WITHOUT ROWID; } breakpoint do_execsql_test 18.1.1 { ALTER TABLE t0 RENAME COLUMN c0 TO c1; } do_execsql_test 18.1.2 { SELECT sql FROM sqlite_master; } {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1)) WITHOUT ROWID}}
<
590 591 592 593 594 595 596
597 598 599 600 601 602 603
}
#------------------------------------------------------------------------- reset_db do_execsql_test 18.1.0 { CREATE TABLE t0 (c0 INTEGER, PRIMARY KEY(c0)) WITHOUT ROWID; }
do_execsql_test 18.1.1 { ALTER TABLE t0 RENAME COLUMN c0 TO c1; } do_execsql_test 18.1.2 { SELECT sql FROM sqlite_master; } {{CREATE TABLE t0 (c1 INTEGER, PRIMARY KEY(c1)) WITHOUT ROWID}}
︙
︙
632 633 634 635 636 637 638 639 640 641 642 643
644
# Ticket 4722bdab08cb14 reset_db do_execsql_test 20.0 { CREATE TABLE a(a); CREATE VIEW b AS SELECT(SELECT *FROM c JOIN a USING(d, a, a, a) JOIN a) IN(); } do_execsql_test 20.1 { ALTER TABLE a RENAME a TO e; } {}
finish_test
<
631 632 633 634 635 636 637
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
# Ticket 4722bdab08cb14 reset_db do_execsql_test 20.0 { CREATE TABLE a(a); CREATE VIEW b AS SELECT(SELECT *FROM c JOIN a USING(d, a, a, a) JOIN a) IN(); }
do_execsql_test 20.1 { ALTER TABLE a RENAME a TO e; } {}
reset_db do_execsql_test 21.0 { CREATE TABLE a(b); CREATE VIEW c AS SELECT NULL INTERSECT SELECT NULL ORDER BY likelihood(NULL, (d, (SELECT c))); } {} do_catchsql_test 21.1 { SELECT likelihood(NULL, (d, (SELECT c))); } {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}} do_catchsql_test 21.2 { SELECT * FROM c; } {1 {1st ORDER BY term does not match any column in the result set}} do_catchsql_test 21.3 { ALTER TABLE a RENAME TO e; } {1 {error in view c: 1st ORDER BY term does not match any column in the result set}}
finish_test
Modified test/window1.test from [cec56b9a0a] to [4aa2a388e5].
︙
︙
1589 1590 1591 1592 1593 1594 1595 1596
1597
} {12 12 12}
do_execsql_test 48.1 { SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x)) FROM (SELECT (SELECT sum(a) FROM t1 GROUP BY a) AS x FROM t1); } {2 2 2}
finish_test
1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607
} {12 12 12}
do_execsql_test 48.1 { SELECT (SELECT max(x)OVER(ORDER BY x) + min(x)OVER(ORDER BY x)) FROM (SELECT (SELECT sum(a) FROM t1 GROUP BY a) AS x FROM t1); } {2 2 2}
# 2020-04-03 ticket af4556bb5c285c08
reset_db do_catchsql_test 51.1 { CREATE TABLE a(b, c); SELECT c FROM a GROUP BY c HAVING(SELECT(sum(b) OVER(ORDER BY b), sum(b) OVER(PARTITION BY min(DISTINCT c), c ORDER BY b))); } {1 {row value misused}}
finish_test