wasCSharpSQLite – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | |||
4 | using i64 = System.Int64; |
||
5 | using u8 = System.Byte; |
||
6 | using u32 = System.UInt32; |
||
7 | using u64 = System.UInt64; |
||
8 | |||
9 | namespace Community.CsharpSqlite |
||
10 | { |
||
11 | public partial class Sqlite3 |
||
12 | { |
||
13 | /* |
||
14 | ** 2001 September 15 |
||
15 | ** |
||
16 | ** The author disclaims copyright to this source code. In place of |
||
17 | ** a legal notice, here is a blessing: |
||
18 | ** |
||
19 | ** May you do good and not evil. |
||
20 | ** May you find forgiveness for yourself and forgive others. |
||
21 | ** May you share freely, never taking more than you give. |
||
22 | ** |
||
23 | ************************************************************************* |
||
24 | ** This file contains code to implement a pseudo-random number |
||
25 | ** generator (PRNG) for SQLite. |
||
26 | ** |
||
27 | ** Random numbers are used by some of the database backends in order |
||
28 | ** to generate random integer keys for tables or random filenames. |
||
29 | ************************************************************************* |
||
30 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
31 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
32 | ** |
||
33 | ** SQLITE_SOURCE_ID: 2010-08-23 18:52:01 42537b60566f288167f1b5864a5435986838e3a3 |
||
34 | ** |
||
35 | ************************************************************************* |
||
36 | */ |
||
37 | //#include "sqliteInt.h" |
||
38 | |||
39 | |||
40 | /* All threads share a single random number generator. |
||
41 | ** This structure is the current state of the generator. |
||
42 | */ |
||
43 | public class sqlite3PrngType |
||
44 | { |
||
45 | public bool isInit; /* True if initialized */ |
||
46 | public int i; |
||
47 | public int j; /* State variables */ |
||
48 | public u8[] s = new u8[256]; /* State variables */ |
||
49 | |||
50 | public sqlite3PrngType Copy() |
||
51 | { |
||
52 | sqlite3PrngType cp = (sqlite3PrngType)MemberwiseClone(); |
||
53 | cp.s = new u8[s.Length]; |
||
54 | Array.Copy( s, cp.s, s.Length ); |
||
55 | return cp; |
||
56 | } |
||
57 | } |
||
58 | public static sqlite3PrngType sqlite3Prng = new sqlite3PrngType(); |
||
59 | /* |
||
60 | ** Get a single 8-bit random value from the RC4 PRNG. The Mutex |
||
61 | ** must be held while executing this routine. |
||
62 | ** |
||
63 | ** Why not just use a library random generator like lrand48() for this? |
||
64 | ** Because the OP_NewRowid opcode in the VDBE depends on having a very |
||
65 | ** good source of random numbers. The lrand48() library function may |
||
66 | ** well be good enough. But maybe not. Or maybe lrand48() has some |
||
67 | ** subtle problems on some systems that could cause problems. It is hard |
||
68 | ** to know. To minimize the risk of problems due to bad lrand48() |
||
69 | ** implementations, SQLite uses this random number generator based |
||
70 | ** on RC4, which we know works very well. |
||
71 | ** |
||
72 | ** (Later): Actually, OP_NewRowid does not depend on a good source of |
||
73 | ** randomness any more. But we will leave this code in all the same. |
||
74 | */ |
||
75 | static u8 randomu8() |
||
76 | { |
||
77 | u8 t; |
||
78 | |||
79 | /* The "wsdPrng" macro will resolve to the pseudo-random number generator |
||
80 | ** state vector. If writable static data is unsupported on the target, |
||
81 | ** we have to locate the state vector at run-time. In the more common |
||
82 | ** case where writable static data is supported, wsdPrng can refer directly |
||
83 | ** to the "sqlite3Prng" state vector declared above. |
||
84 | */ |
||
85 | #if SQLITE_OMIT_WSD |
||
86 | struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng); |
||
87 | //# define wsdPrng p[0] |
||
88 | #else |
||
89 | //# define wsdPrng sqlite3Prng |
||
90 | sqlite3PrngType wsdPrng = sqlite3Prng; |
||
91 | #endif |
||
92 | |||
93 | |||
94 | /* Initialize the state of the random number generator once, |
||
95 | ** the first time this routine is called. The seed value does |
||
96 | ** not need to contain a lot of randomness since we are not |
||
97 | ** trying to do secure encryption or anything like that... |
||
98 | ** |
||
99 | ** Nothing in this file or anywhere else in SQLite does any kind of |
||
100 | ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random |
||
101 | ** number generator) not as an encryption device. |
||
102 | */ |
||
103 | if ( !wsdPrng.isInit ) |
||
104 | { |
||
105 | int i; |
||
106 | u8[] k = new u8[256]; |
||
107 | wsdPrng.j = 0; |
||
108 | wsdPrng.i = 0; |
||
109 | sqlite3OsRandomness( sqlite3_vfs_find( string.Empty ), 256, k ); |
||
110 | for ( i = 0; i < 255; i++ ) |
||
111 | { |
||
112 | wsdPrng.s[i] = (u8)i; |
||
113 | } |
||
114 | for ( i = 0; i < 255; i++ ) |
||
115 | { |
||
116 | wsdPrng.j = (u8)( wsdPrng.j + wsdPrng.s[i] + k[i] ); |
||
117 | t = wsdPrng.s[wsdPrng.j]; |
||
118 | wsdPrng.s[wsdPrng.j] = wsdPrng.s[i]; |
||
119 | wsdPrng.s[i] = t; |
||
120 | } |
||
121 | wsdPrng.isInit = true; |
||
122 | } |
||
123 | |||
124 | /* Generate and return single random u8 |
||
125 | */ |
||
126 | wsdPrng.i++; |
||
127 | t = wsdPrng.s[(u8)wsdPrng.i]; |
||
128 | wsdPrng.j = (u8)( wsdPrng.j + t ); |
||
129 | wsdPrng.s[(u8)wsdPrng.i] = wsdPrng.s[wsdPrng.j]; |
||
130 | wsdPrng.s[wsdPrng.j] = t; |
||
131 | t += wsdPrng.s[(u8)wsdPrng.i]; |
||
132 | return wsdPrng.s[t]; |
||
133 | } |
||
134 | |||
135 | /* |
||
136 | ** Return N random u8s. |
||
137 | */ |
||
138 | static void sqlite3_randomness( int N, ref i64 pBuf ) |
||
139 | { |
||
140 | ////u8[] zBuf = new u8[N]; |
||
141 | pBuf = 0; |
||
142 | #if SQLITE_THREADSAFE |
||
143 | sqlite3_mutex mutex = sqlite3MutexAlloc( SQLITE_MUTEX_STATIC_PRNG ); |
||
144 | #endif |
||
145 | sqlite3_mutex_enter( mutex ); |
||
146 | while ( N-- > 0 ) |
||
147 | { |
||
148 | pBuf = (u32)( ( pBuf << 8 ) + randomu8() );// zBuf[N] = randomu8(); |
||
149 | } |
||
150 | sqlite3_mutex_leave( mutex ); |
||
151 | } |
||
152 | |||
153 | static void sqlite3_randomness( byte[] pBuf, int Offset, int N ) |
||
154 | { |
||
155 | i64 iBuf = System.DateTime.Now.Ticks; |
||
156 | #if SQLITE_THREADSAFE |
||
157 | sqlite3_mutex mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG); |
||
158 | #endif |
||
159 | sqlite3_mutex_enter( mutex ); |
||
160 | while ( N-- > 0 ) |
||
161 | { |
||
162 | iBuf = (u32)( ( iBuf << 8 ) + randomu8() );// zBuf[N] = randomu8(); |
||
163 | pBuf[Offset++] = (byte)iBuf; |
||
164 | } |
||
165 | sqlite3_mutex_leave( mutex ); |
||
166 | } |
||
167 | |||
168 | #if !SQLITE_OMIT_BUILTIN_TEST |
||
169 | /* |
||
170 | ** For testing purposes, we sometimes want to preserve the state of |
||
171 | ** PRNG and restore the PRNG to its saved state at a later time, or |
||
172 | ** to reset the PRNG to its initial state. These routines accomplish |
||
173 | ** those tasks. |
||
174 | ** |
||
175 | ** The sqlite3_test_control() interface calls these routines to |
||
176 | ** control the PRNG. |
||
177 | */ |
||
178 | static sqlite3PrngType sqlite3SavedPrng = null; |
||
179 | static void sqlite3PrngSaveState() |
||
180 | { |
||
181 | sqlite3SavedPrng = sqlite3Prng.Copy(); |
||
182 | // memcpy( |
||
183 | // &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), |
||
184 | // &GLOBAL(struct sqlite3PrngType, sqlite3Prng), |
||
185 | // sizeof(sqlite3Prng) |
||
186 | //); |
||
187 | } |
||
188 | static void sqlite3PrngRestoreState() |
||
189 | { |
||
190 | sqlite3Prng = sqlite3SavedPrng.Copy(); |
||
191 | //memcpy( |
||
192 | // &GLOBAL(struct sqlite3PrngType, sqlite3Prng), |
||
193 | // &GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng), |
||
194 | // sizeof(sqlite3Prng) |
||
195 | //); |
||
196 | } |
||
197 | static void sqlite3PrngResetState() |
||
198 | { |
||
199 | sqlite3Prng.isInit = false;// GLOBAL(struct sqlite3PrngType, sqlite3Prng).isInit = 0; |
||
200 | } |
||
201 | #endif //* SQLITE_OMIT_BUILTIN_TEST */ |
||
202 | } |
||
203 | } |