System.Data.SQLite
Check-in [09db2a0a1b]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Make the SAVEPOINT names used for nested transactions much less predictable.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tkt-1f7bfff467
Files: files | file ages | folders
SHA1: 09db2a0a1b37532d62bca59cba34e4baf00e434f
User & Date: mistachkin 2016-10-29 22:19:51
References
2016-10-29
22:22 Ticket [1f7bfff467] SQLiteTransaction: critical rollback bug status still Open with 3 other changes artifact: 9018a25250 user: mistachkin
Context
2016-10-30
03:27
Do not try to rollback a nested transaction after it has been committed. check-in: 2bed8a7ba9 user: mistachkin tags: tkt-1f7bfff467
2016-10-29
22:19
Make the SAVEPOINT names used for nested transactions much less predictable. check-in: 09db2a0a1b user: mistachkin tags: tkt-1f7bfff467
2016-10-28
21:30
Improve the new test. check-in: 588b7768a0 user: mistachkin tags: tkt-1f7bfff467
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to System.Data.SQLite/SQLiteTransaction.cs.

     4      4    *
     5      5    * Released to the public domain, use at your own risk!
     6      6    ********************************************************/
     7      7   
     8      8   namespace System.Data.SQLite
     9      9   {
    10     10       using System;
           11  +    using System.Collections.Generic;
    11     12       using System.Data;
    12     13       using System.Data.Common;
    13     14       using System.Threading;
    14     15   
    15     16       ///////////////////////////////////////////////////////////////////////////////////////////////
    16     17   
    17     18       /// <summary>
................................................................................
    30     31           private int _version;
    31     32   
    32     33           /// <summary>
    33     34           /// The isolation level for this transaction.
    34     35           /// </summary>
    35     36           private IsolationLevel _level;
    36     37   
           38  +        /// <summary>
           39  +        /// The SAVEPOINT names for each transaction level.
           40  +        /// </summary>
           41  +        private Dictionary<int, string> _savePointNames;
           42  +
           43  +        /// <summary>
           44  +        /// Random number generator used when creating new SAVEPOINT names.
           45  +        /// </summary>
           46  +        private Random _random;
           47  +
    37     48           ///////////////////////////////////////////////////////////////////////////////////////////////
    38     49   
    39     50           /// <summary>
    40     51           /// Constructs the transaction object, binding it to the supplied connection
    41     52           /// </summary>
    42     53           /// <param name="connection">The connection to open a transaction on</param>
    43     54           /// <param name="deferredLock">TRUE to defer the writelock, or FALSE to lock immediately</param>
................................................................................
   292    303           /// </summary>
   293    304           /// <param name="level">
   294    305           /// The transaction level associated with the connection.
   295    306           /// </param>
   296    307           /// <returns>
   297    308           /// The name of the savepoint -OR- null if it cannot be constructed.
   298    309           /// </returns>
   299         -        private static string GetSavePointName(
          310  +        private string GetSavePointName(
   300    311               int level
   301    312               )
   302    313           {
   303         -            return String.Format("sqlite_dotnet_savepoint_{0}", level);
          314  +            if (_savePointNames == null)
          315  +                _savePointNames = new Dictionary<int, string>();
          316  +
          317  +            string name;
          318  +
          319  +            if (!_savePointNames.TryGetValue(level, out name))
          320  +            {
          321  +                if (_random == null)
          322  +                    _random = new Random();
          323  +
          324  +                name = String.Format(
          325  +                    "sqlite_dotnet_savepoint_{0}_{1}", level, _random.Next());
          326  +
          327  +                _savePointNames[level] = name;
          328  +            }
          329  +
          330  +            return name;
   304    331           }
   305    332   
   306    333           ///////////////////////////////////////////////////////////////////////////////////////////////
   307    334   
   308    335           /// <summary>
   309    336           /// Checks the state of this transaction, optionally throwing an exception if a state inconsistency is found.
   310    337           /// </summary>