2012-01-23 33 views
6

, bazı arka plan:Daha SQLite yolsuzluk algılama

Benim Android uygulaması dört sütunlu satırların bir sürü DB tablo vardır. Sunucuya istek gönderir ve sunucu yalnızca bu dört değerin tümü "geçerli" olduğunda yanıt verir. Binlerce kullanıcının bir kısmı kendileri için bir şeylerin işe yaramadığını bildirdi (bir süredir sunucudan sonuç alamıyorlardı) - sorunun nedenini anlamaya çalışıyordum ve bunun tek olası sebebi olduğu ortaya çıktı. Algılanmayan DB bozulması.

ACRA günlüklerinde SQL hatası olan bazı iletiler var, ancak bunlar bozuk olduğundan dolayı bu dosyayı açamayacaklardı. Bu bana bir ipucu verdi, ancak hala bu sorunun olduğuna ikna olmamıştım.

import random 
import array 
import sqlite3 

db = array.array('B') 
db.fromstring(open('db').read()) 

ta = [x for x in sqlite3.connect('db').execute('SELECT * FROM table ORDER BY _id')] 

results = [0,0,0,0] 
tries = 1000 

for i in xrange(0,tries): 
    work = db[:] 
    while work == db: 
     for j in xrange(0,random.randint(1,5)): 
      work[random.randint(1,len(db))-1] = random.randint(0,255) 

    work.tofile(open('outdb','w')) 

    try: 
     c = sqlite3.connect('outdb') 
     results[0] += 1 

     for r in c.execute('PRAGMA integrity_check;'): 
     results[1] += 1 if (r[0] == 'ok') else 0 
    except: 
     continue  

    try: 
     results[3] += 1 if [x for x in c.execute('SELECT * FROM table ORDER BY _id')] != ta else 0 
     results[2] += 1 
    except: 
     c.close() 
     continue 

print 'Results for '+str(tries)+' tests:' 
print 'Creating connection failed '+str(tries-results[0])+ ' times' 
print 'Integrity check failed '+str(results[0]-results[1])+ ' times' 
print 'Running a SELECT * query failed '+str(results[1]-results[2])+ ' times' 
print 'Data was succesfully altered '+str(results[3])+ ' times' 

sonuç bu şekilde "düzenleme" tablo veri tamamen mümkün olduğunu göstermiştir: Yani, SQLite bununla başa nasıl rastgele VT dosyasında bayt ve kontrolleri değiştiren çok basit Python komut yarattı

Results for 1000 tests: 
Creating connection failed 0 times 
Integrity check failed 503 times 
Running a SELECT * query failed 289 times 
Data was succesfully altered 193 times 

Bu bir sorgu yapmayı bütünlük çekle fark edilmemeye giden değişiklikler yarısını başarısız olduğunu görmek genelde ilginç, ama benim için en ilginç şey bir şey için başvurum gereksiz kılan benim DB rastgele bayt takas olabilmesidir Kullanıcılarımın bir parçası.

SQLite web sitesinde ve ayrıca StackOverflow üzerinde olası yolsuzluk nedenlerini okudum, örn. Uygulamayı kapatmak için zorlamak DB'ye zarar verebilir. Daha hızlı ve daha sağlam bir DB bütünlüğü kontrolü gerçekleştirmenin mümkün olup olmadığını bilmek isterim.

Başlangıçta (otomatik tamamlama için) tüm tablonun bir sütunundaki verileri okuyorum, bu yüzden bazı değerlerin tüm değerlerden hesaplanmasını düşünmüştüm - bazı karma işlevleri olduğu için bunun oldukça iyi olacağını düşünüyorum. Sadece doğruluk kontrolleri yapmak için tasarlandı, ama belki de daha basit, daha hızlı ve daha iyi bir çözüm var.

+0

Bu sorunun yanıtında önerildiği gibi: http://stackoverflow.com/questions/11490250/does-sqlite-checksum-its-data Verilerinizi ileri hata düzeltmesi kullanarak kodlayabilirsiniz. Belki daha basit ya da daha hızlı değil (bir karma mantıklı ve basit bir çözüm gibi görünüyor), ama belki daha iyi. Hataları düzeltme şansınız var, sadece onları tespit etmek değil. – bsa

+0

Bu soru biraz eski, ama [bu cevap] 'dan bahsetmek istedim (http://stackoverflow.com/questions/12418600/how-do-you-determine-if-an-sqlite-or-sqback-is- bozuk-in-java), veri (?) * üzerinde bir çeşit tarama * yapan PRAGMA quick_check; Yukarıdaki test çantasında bunun ne tür sonuçlar vereceğini merak ediyorum ama nasıl entegre edeceğinizden emin değilim. ** DÜZENLEME: [dökümantasyon] (http://www.sqlite.org/pragma.html#pragma_integrity_check) '' quick_check' '' identity_check''nın daha hızlı bir versiyonudur. ** Ah. –

cevap

1

Böyle bir SQLite özelliği bilmiyorum, bu yüzden bir karma hesaplamanın en basit çözüm olduğunu söyleyebilirim, bir başlangıç ​​için MessageDigest sınıfına bir göz atın.