1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.database.sqlite.cts; 18 19 20 import android.content.Context; 21 import android.database.sqlite.SQLiteDatabase; 22 import android.database.sqlite.SQLiteDatabaseCorruptException; 23 import android.test.AndroidTestCase; 24 25 /** 26 * This CTS test verifies Magellan SQLite Security Vulnerability. 27 * Without the fix, the last statement in each test case triggers a segmentation fault and the test 28 * fails. 29 * With the fix, the last statement in each test case triggers SQLiteDatabaseCorruptException with 30 * message "database disk image is malformed (code 267 SQLITE_CORRUPT_VTAB)", this is expected 31 * behavior that we are crashing and we are not leaking data. 32 */ 33 public class SQLiteSecurityTest extends AndroidTestCase { 34 private static final String DATABASE_NAME = "database_test.db"; 35 36 private SQLiteDatabase mDatabase; 37 38 @Override setUp()39 protected void setUp() throws Exception { 40 super.setUp(); 41 42 getContext().deleteDatabase(DATABASE_NAME); 43 mDatabase = getContext().openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, 44 null); 45 assertNotNull(mDatabase); 46 } 47 48 @Override tearDown()49 protected void tearDown() throws Exception { 50 mDatabase.close(); 51 getContext().deleteDatabase(DATABASE_NAME); 52 53 super.tearDown(); 54 } 55 testScript1()56 public void testScript1() { 57 mDatabase.beginTransaction(); 58 mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts3;"); 59 mDatabase.execSQL("INSERT INTO ft_content VALUES(1,'aback');"); 60 mDatabase.execSQL("INSERT INTO ft_content VALUES(2,'abaft');"); 61 mDatabase.execSQL("INSERT INTO ft_content VALUES(3,'abandon');"); 62 mDatabase.execSQL("INSERT INTO ft_segdir VALUES(0,0,0,0,'0 29',X" 63 + "'0005616261636b03010200ffffffff070266740302020003046e646f6e03030200');"); 64 mDatabase.setTransactionSuccessful(); 65 mDatabase.endTransaction(); 66 try { 67 mDatabase.execSQL("SELECT * FROM ft WHERE ft MATCH 'abandon';"); 68 } catch (SQLiteDatabaseCorruptException e) { 69 return; 70 } 71 fail("Expecting a SQLiteDatabaseCorruptException"); 72 } 73 testScript2()74 public void testScript2() { 75 mDatabase.beginTransaction(); 76 mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts3;"); 77 mDatabase.execSQL("INSERT INTO ft_segments VALUES(1," 78 + "X'0004616263300301020003013103020200040130030b0200040131030c0200');"); 79 mDatabase.execSQL("INSERT INTO ft_segments VALUES(2," 80 + "X'00056162633132030d0200040133030e0200040134030f020004013503100200');"); 81 mDatabase.execSQL("INSERT INTO ft_segments VALUES(3," 82 + "X'0005616263313603110200040137031202000401380313020004013903140200');"); 83 mDatabase.execSQL("INSERT INTO ft_segments VALUES(4," 84 + "X'00046162633203030200030133030402000301340305020003013503060200');"); 85 mDatabase.execSQL("INSERT INTO ft_segments VALUES(5," 86 + "X'000461626336030702000301370308020003013803090200030139030a0200');"); 87 mDatabase.execSQL("INSERT INTO ft_segdir " 88 + "VALUES(0,0,1,5,'5 157',X'0101056162633132ffffffff070236030132030136');"); 89 mDatabase.setTransactionSuccessful(); 90 mDatabase.endTransaction(); 91 try { 92 mDatabase.execSQL("SELECT * FROM ft WHERE ft MATCH 'abc20';"); 93 } catch (SQLiteDatabaseCorruptException e) { 94 return; 95 } 96 fail("Expecting a SQLiteDatabaseCorruptException"); 97 } 98 testScript3()99 public void testScript3() { 100 mDatabase.beginTransaction(); 101 mDatabase.execSQL("CREATE VIRTUAL TABLE ft USING fts4;"); 102 mDatabase.execSQL("INSERT INTO ft_segments VALUES" 103 + "(1,X'00046162633003010200040178030202000501780303020003013103040200');"); 104 mDatabase.execSQL("INSERT INTO ft_segments VALUES" 105 + "(2,X'00056162633130031f0200ffffffff07ff5566740302020003046e646f6e03030200');"); 106 mDatabase.execSQL("INSERT INTO ft_segments VALUES(384,NULL);"); 107 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 108 + "(0,0,0,0,'0 24',X'000561626331780305020005017803060200');"); 109 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 110 + " (0,1,0,0,'0 24',X'000461626332030702000401780308020005017803090200');"); 111 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 112 + "(0,2,0,0,'0 24',X'000461626333030a0200040178030b0200050178030c0200');"); 113 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" + 114 "(0,3,0,0,'0 24',X'000461626334030d0200040178030e0200050178030f0200');"); 115 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 116 + "(0,4,0,0,'0 24',X'000461626335031002000401780311020005017803120200');"); 117 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 118 + "(0,5,0,0,'0 24',X'000461626336031302000401780314020005017803150200');"); 119 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 120 + "(0,6,0,0,'0 24',X'000461626337031602000401780317020005017803180200');"); 121 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 122 + "(0,7,0,0,'0 24',X'00046162633803190200040178031a0200050178031b0200');"); 123 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 124 + "(0,8,0,0,'0 24',X'000461626339031c0200040178031d0200050178031e0200');"); 125 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 126 + "(0,9,0,0,'0 25',X'00066162633130780320020006017803210200');"); 127 mDatabase.execSQL("INSERT INTO ft_segdir VALUES" 128 + "(0,10,0,0,'0 25',X'00056162633131032202000501780323020006017803240200');"); 129 mDatabase.execSQL("INSERT INTO ft_segdir VALUES(1,0,1,2,'384 -42',X'0101056162633130');"); 130 mDatabase.execSQL("INSERT INTO ft_stat VALUES(1,X'000b');"); 131 mDatabase.execSQL("PRAGMA writable_schema=OFF;"); 132 mDatabase.setTransactionSuccessful(); 133 mDatabase.endTransaction(); 134 try { 135 mDatabase.execSQL("INSERT INTO ft(ft) VALUES('merge=1,4');"); 136 } catch (SQLiteDatabaseCorruptException e) { 137 return; 138 } 139 fail("Expecting a SQLiteDatabaseCorruptException"); 140 } 141 } 142 143 144 145 146 147 148 149 150 151 152 153