579 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			579 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html><head>
 | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8">
 | |
| <link href="sqlite.css" rel="stylesheet">
 | |
| <title>Pointer Passing Interfaces</title>
 | |
| <!-- path= -->
 | |
| </head>
 | |
| <body>
 | |
| <div class=nosearch>
 | |
| <a href="index.html">
 | |
| <img class="logo" src="images/sqlite370_banner.gif" alt="SQLite" border="0">
 | |
| </a>
 | |
| <div><!-- IE hack to prevent disappearing logo --></div>
 | |
| <div class="tagline desktoponly">
 | |
| Small. Fast. Reliable.<br>Choose any three.
 | |
| </div>
 | |
| <div class="menu mainmenu">
 | |
| <ul>
 | |
| <li><a href="index.html">Home</a>
 | |
| <li class='mobileonly'><a href="javascript:void(0)" onclick='toggle_div("submenu")'>Menu</a>
 | |
| <li class='wideonly'><a href='about.html'>About</a>
 | |
| <li class='desktoponly'><a href="docs.html">Documentation</a>
 | |
| <li class='desktoponly'><a href="download.html">Download</a>
 | |
| <li class='wideonly'><a href='copyright.html'>License</a>
 | |
| <li class='desktoponly'><a href="support.html">Support</a>
 | |
| <li class='desktoponly'><a href="prosupport.html">Purchase</a>
 | |
| <li class='search' id='search_menubutton'>
 | |
| <a href="javascript:void(0)" onclick='toggle_search()'>Search</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="menu submenu" id="submenu">
 | |
| <ul>
 | |
| <li><a href='about.html'>About</a>
 | |
| <li><a href='docs.html'>Documentation</a>
 | |
| <li><a href='download.html'>Download</a>
 | |
| <li><a href='support.html'>Support</a>
 | |
| <li><a href='prosupport.html'>Purchase</a>
 | |
| </ul>
 | |
| </div>
 | |
| <div class="searchmenu" id="searchmenu">
 | |
| <form method="GET" action="search">
 | |
| <select name="s" id="searchtype">
 | |
| <option value="d">Search Documentation</option>
 | |
| <option value="c">Search Changelog</option>
 | |
| </select>
 | |
| <input type="text" name="q" id="searchbox" value="">
 | |
| <input type="submit" value="Go">
 | |
| </form>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_div(nm) {
 | |
| var w = document.getElementById(nm);
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| }else{
 | |
| w.style.display = "block";
 | |
| }
 | |
| }
 | |
| function toggle_search() {
 | |
| var w = document.getElementById("searchmenu");
 | |
| if( w.style.display=="block" ){
 | |
| w.style.display = "none";
 | |
| } else {
 | |
| w.style.display = "block";
 | |
| setTimeout(function(){
 | |
| document.getElementById("searchbox").focus()
 | |
| }, 30);
 | |
| }
 | |
| }
 | |
| function div_off(nm){document.getElementById(nm).style.display="none";}
 | |
| window.onbeforeunload = function(e){div_off("submenu");}
 | |
| /* Disable the Search feature if we are not operating from CGI, since */
 | |
| /* Search is accomplished using CGI and will not work without it. */
 | |
| if( !location.origin || !location.origin.match || !location.origin.match(/http/) ){
 | |
| document.getElementById("search_menubutton").style.display = "none";
 | |
| }
 | |
| /* Used by the Hide/Show button beside syntax diagrams, to toggle the */
 | |
| function hideorshow(btn,obj){
 | |
| var x = document.getElementById(obj);
 | |
| var b = document.getElementById(btn);
 | |
| if( x.style.display!='none' ){
 | |
| x.style.display = 'none';
 | |
| b.innerHTML='show';
 | |
| }else{
 | |
| x.style.display = '';
 | |
| b.innerHTML='hide';
 | |
| }
 | |
| return false;
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| <div class=fancy>
 | |
| <div class=nosearch>
 | |
| <div class="fancy_title">
 | |
| Pointer Passing Interfaces
 | |
| </div>
 | |
| <div class="fancy_toc">
 | |
| <a onclick="toggle_toc()">
 | |
| <span class="fancy_toc_mark" id="toc_mk">►</span>
 | |
| Table Of Contents
 | |
| </a>
 | |
| <div id="toc_sub"><div class="fancy-toc1"><a href="#overview">1. Overview</a></div>
 | |
| <div class="fancy-toc1"><a href="#a_brief_history_of_pointer_passing_in_sqlite">2. A Brief History Of Pointer Passing In SQLite</a></div>
 | |
| <div class="fancy-toc2"><a href="#upping_the_threat_level">2.1. Upping The Threat Level</a></div>
 | |
| <div class="fancy-toc2"><a href="#preventing_forged_pointers">2.2. Preventing Forged Pointers</a></div>
 | |
| <div class="fancy-toc2"><a href="#pointer_leaks">2.3. Pointer Leaks</a></div>
 | |
| <div class="fancy-toc1"><a href="#the_new_pointer_passing_interfaces">3. The New Pointer-Passing Interfaces</a></div>
 | |
| <div class="fancy-toc2"><a href="#pointer_types">3.1. Pointer Types</a></div>
 | |
| <div class="fancy-toc3"><a href="#pointer_types_are_static_strings">3.1.1. Pointer types are static strings</a></div>
 | |
| <div class="fancy-toc2"><a href="#destructor_functions">3.2. Destructor Functions</a></div>
 | |
| <div class="fancy-toc1"><a href="#restrictions_on_the_use_of_pointer_values">4. Restrictions On The Use of Pointer Values</a></div>
 | |
| <div class="fancy-toc1"><a href="#summary">5. Summary</a></div>
 | |
| </div>
 | |
| </div>
 | |
| <script>
 | |
| function toggle_toc(){
 | |
| var sub = document.getElementById("toc_sub")
 | |
| var mk = document.getElementById("toc_mk")
 | |
| if( sub.style.display!="block" ){
 | |
| sub.style.display = "block";
 | |
| mk.innerHTML = "▼";
 | |
| } else {
 | |
| sub.style.display = "none";
 | |
| mk.innerHTML = "►";
 | |
| }
 | |
| }
 | |
| </script>
 | |
| </div>
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| <h1 id="overview"><span>1. </span>Overview</h1>
 | |
| 
 | |
| <p>
 | |
| Three new "_pointer()" interfaces were added to SQLite 3.20.0 (2017-08-01):
 | |
| </p><ul>
 | |
| <li> <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a>,
 | |
| </li><li> <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a>, and
 | |
| </li><li> <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a>.
 | |
| </li></ul>
 | |
| 
 | |
| <p>Questions and confusion quickly arose
 | |
| on the <a href="support.html#mailinglists">mailing lists</a> about the purpose behind these new interfaces,
 | |
| why they were introduced, and what problem they solve.  This essay attempts
 | |
| to answer those questions and clear up the confusion.
 | |
| 
 | |
| </p><h1 id="a_brief_history_of_pointer_passing_in_sqlite"><span>2. </span>A Brief History Of Pointer Passing In SQLite</h1>
 | |
| 
 | |
| <p>
 | |
| It is sometimes convenient for SQLite extensions to
 | |
| communicate non-SQL values between subcomponents or between the extension
 | |
| and the application.  Some examples:
 | |
| 
 | |
| </p><ul>
 | |
| <li><p>
 | |
| In the <a href="fts3.html">FTS3</a> extension, the 
 | |
| <a href="fts3.html#full_text_index_queries">MATCH operator</a> (which does the full-text search)
 | |
| needs to communicate details of matching entries 
 | |
| to the <a href="fts3.html#snippet">snippet()</a>, <a href="fts3.html#offsets">offsets()</a>,
 | |
| and <a href="fts3.html#matchinfo">matchinfo()</a> functions so that those functions can convert the details
 | |
| of the match into useful output.
 | |
| 
 | |
| </p></li><li><p>
 | |
| In order for an application to 
 | |
| <a href="fts5.html#extending_fts5">add new extensions to FTS5</a>, such as new tokenizers, 
 | |
| the application needs a pointer to the "fts5_api" object.
 | |
| 
 | |
| </p></li><li><p>
 | |
| In the <a href="carray.html">CARRAY extension</a>, the application needs to tell the 
 | |
| extension the
 | |
| location of a C-language array that contains the data for the table-valued
 | |
| function that the extension implements.
 | |
| </p></li></ul>
 | |
| 
 | |
| <p>
 | |
| The traditional way of communicating this information was to transform a
 | |
| C-language pointer into a BLOB or a 64-bit integer, then move that BLOB or
 | |
| integer through SQLite using the usual interfaces like
 | |
| <a href="c3ref/bind_blob.html">sqlite3_bind_blob()</a>, <a href="c3ref/result_blob.html">sqlite3_result_blob()</a>, <a href="c3ref/value_blob.html">sqlite3_value_blob()</a> or
 | |
| the integer equivalents.
 | |
| 
 | |
| </p><h2 id="upping_the_threat_level"><span>2.1. </span>Upping The Threat Level</h2>
 | |
| 
 | |
| <p>
 | |
| Passing around pointers as if they were integers or BLOBs is easy,
 | |
| effective, and works well in an environment where the application
 | |
| components are all friendly toward one another.  However, passing pointers
 | |
| as integers and BLOBs allows hostile SQL text to forge invalid pointers that
 | |
| can carry out mischief.
 | |
| 
 | |
| </p><p>
 | |
| For example, the first argument to the <a href="fts3.html#snippet">snippet()</a> function is supposed to
 | |
| be a special column of the FTS3 table that contains a pointer to an fts3cursor
 | |
| object that contains information about the current full text search match.
 | |
| That pointer was formerly passed as a BLOB.  
 | |
| For example, if the FTS3 table is named "t1" and has a column named "cx",
 | |
| one might write:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT snippet(t1) FROM t1 WHERE cx MATCH $pattern;
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| But if a hacker is able to run arbitrary SQL, he might run a slightly
 | |
| different query, like this:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT hex(t1) FROM t1 WHERE cx MATCH $pattern;
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| Because the pointer is passed in the t1 column of the t1
 | |
| table as a BLOB (in older versions of SQLite), such a query would have 
 | |
| shown the value of the
 | |
| pointer in hex.  The attacker could then modify that pointer to try to
 | |
| get the snippet() function to modify memory in some other part of 
 | |
| the application address space instead of the fts3cursor object it 
 | |
| was supposed to be operating on:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT snippet(x'6092310100000000') FROM t1 WHERE cx MATCH $pattern;
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| Historically, this was not considered a threat.  The argument was that if
 | |
| a hostile agent is able to inject arbitrary SQL text into the application,
 | |
| then that agent is already in full control of the application, so
 | |
| letting the hostile agent forge a pointer does not give the agent
 | |
| any new capability.
 | |
| 
 | |
| </p><p>
 | |
| For most cases, it is true that potential attackers have no way of injecting
 | |
| arbitrary SQL, and so most uses of SQLite are immune to the attack above.
 | |
| But there are some notable exceptions.  To wit:
 | |
| 
 | |
| </p><ul>
 | |
| <li><p>
 | |
| The <a href="https://en.wikipedia.org/wiki/Web_SQL_Database">WebSQL</a> interface
 | |
| to webkit allowed any webpage to run arbitrary SQL in the browser
 | |
| for Chrome and Safari.  That arbitrary SQL was supposed to be run inside
 | |
| a sandbox where it could do no harm even if exploited, but that sandbox
 | |
| turned out to be less secure than people supposed.  In the spring of 2017, 
 | |
| one team of hackers was able to root an iMac using a long sequence of 
 | |
| exploits, one of which involved corrupting the pointers passed as BLOB 
 | |
| values to the snippet() FTS3 function of an SQLite database running via
 | |
| the WebSQL interface inside of Safari.
 | |
| 
 | |
| </p></li><li><p>
 | |
| On Android, we are told, there are many services that will blindly 
 | |
| run arbitrary SQL that is passed to them by untrustworthy apps
 | |
| that have been downloaded from dodgy corners of the internet.
 | |
| Android services are suppose to be more guarded about running SQL
 | |
| from unvetted sources.  This author does not have any specific examples
 | |
| to the contrary, but he has heard rumors that they exist.  Even if
 | |
| all Android services are more careful and properly vet all the SQL
 | |
| they run, it would be difficult to audit them
 | |
| all in order to verify that they are safe.  Hence, security-minded people
 | |
| are keen to ensure that no exploits are possible by passing arbitrary
 | |
| SQL text.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The <a href="https://www.fossil-scm.org/">Fossil</a> version control system (designed
 | |
| and written for the purpose of supporting SQLite development) allows
 | |
| mildly trusted users to enter arbitrary SQL for generating trouble-ticket
 | |
| reports.  That SQL is sanitized using the
 | |
| <a href="c3ref/set_authorizer.html">sqlite3_set_authorizer()</a> interface, and no exploits have ever been
 | |
| found.  But this is an example of potentially hostile agents being able to
 | |
| inject arbitrary SQL into the system.
 | |
| </p></li></ul>
 | |
| 
 | |
| <h2 id="preventing_forged_pointers"><span>2.2. </span>Preventing Forged Pointers</h2>
 | |
| 
 | |
| <p>
 | |
| The first attempt at closing security gaps in pointer passing was to
 | |
| prevent pointer values from being forged.  This was accomplished by
 | |
| having the sender attach a subtype to each pointer using
 | |
| <a href="c3ref/result_subtype.html">sqlite3_result_subtype()</a> and having the receiver verify that subtype
 | |
| using <a href="c3ref/value_subtype.html">sqlite3_value_subtype()</a> and reject pointers that had an incorrect
 | |
| subtype.  Since there is no way to attach a subtype to a result using
 | |
| pure SQL, this prevents pointers from being forged using SQL.  The only
 | |
| way to send a pointer is to use C code.  If an attacker can set a subtype,
 | |
| then he is also able to forge a pointer without the help of SQLite.
 | |
| 
 | |
| </p><p>
 | |
| Using subtypes to identify valid pointers prevented the WebSQL exploit.
 | |
| But it turned out to be an incomplete solution.
 | |
| 
 | |
| <a name="ptrleak"></a>
 | |
| 
 | |
| </p><h2 id="pointer_leaks"><span>2.3. </span>Pointer Leaks</h2>
 | |
| 
 | |
| <p>
 | |
| The use of subtypes on pointers prevented pointer forgery using
 | |
| pure SQL.  But subtypes do nothing to prevent an attacker from reading
 | |
| the values of pointers.  In other words, subtypes on pointer values
 | |
| prevent attacks using SQL statements like this:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT snippet(x'6092310100000000') FROM t1 WHERE cx MATCH $pattern;
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| The BLOB argument to snippet() does not have the correct subtype, so the
 | |
| snippet function ignores it, makes no changes to any data structures,
 | |
| and harmlessly returns NULL.
 | |
| 
 | |
| </p><p>
 | |
| But the use of subtypes does nothing to prevent the value of a
 | |
| pointer from being read using SQL code like this:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT hex(t1) FROM t1 WHERE cx MATCH $pattern;
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| What harm could come of that, you ask?  The SQLite developers (including
 | |
| this author) wondered the same thing.  But then security researchers
 | |
| pointed out that knowledge of pointers can help attackers to circumvent
 | |
| address-space randomization defenses.  This is called a "pointer leak".
 | |
| A pointer leak is not itself a vulnerability, but it can aid an attacker
 | |
| in effectively exploiting other vulnerabilities.
 | |
| 
 | |
| </p><h1 id="the_new_pointer_passing_interfaces"><span>3. </span>The New Pointer-Passing Interfaces</h1>
 | |
| 
 | |
| <p>
 | |
| Allowing extension components to pass private information to one another
 | |
| securely and without introducing pointer leaks requires new interfaces:
 | |
| 
 | |
| </p><ul>
 | |
| <li><b><a href="c3ref/bind_blob.html">sqlite3_bind_pointer</a>(S,I,P,T,D)</b> →
 | |
| Bind pointer P of type T to the I-th parameter of prepared statement S.
 | |
| D is an optional destructor function for P.
 | |
| </li><li><b><a href="c3ref/result_blob.html">sqlite3_result_pointer</a>(C,P,T,D)</b> →
 | |
| Return pointer P of type T as the argument of function C.
 | |
| D is an optional destructor function for P.
 | |
| </li><li><b><a href="c3ref/value_blob.html">sqlite3_value_pointer</a>(V,T)</b> →
 | |
| Return the pointer of type T associated with value V, or if V has no
 | |
| associated pointer, or if the pointer on V is of a type different from
 | |
| T, then return NULL.
 | |
| </li></ul>
 | |
| 
 | |
| <p>
 | |
| To SQL, the values created by <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> and 
 | |
| <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> are indistinguishable from NULL.  An
 | |
| SQL statement that tries to use the <a href="lang_corefunc.html#hex">hex()</a> function to read the
 | |
| value of a pointer will get an SQL NULL answer.  The only way to
 | |
| discover whether or not a value has an associated pointer is to
 | |
| use the <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a> interface with the appropriate
 | |
| type string T. 
 | |
| 
 | |
| </p><p>
 | |
| Pointer values read by <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a>
 | |
| cannot be generated by pure SQL.  Hence, it is not possible for SQL to
 | |
| forge pointers.
 | |
| 
 | |
| </p><p>
 | |
| Pointer values generated by <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> and
 | |
| <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> cannot be read by pure SQL.
 | |
| Hence, it is not possible for SQL to leak the value of pointers.
 | |
| 
 | |
| </p><p>
 | |
| In this way the new pointer-passing interface seems to solve all of the
 | |
| security problems associated with passing pointer values from one
 | |
| extension to another in SQLite.
 | |
| 
 | |
| <a name="ptrtyp"></a>
 | |
| 
 | |
| </p><h2 id="pointer_types"><span>3.1. </span>Pointer Types</h2>
 | |
| 
 | |
| <p>
 | |
| The "pointer type" in the last parameter to <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a>,
 | |
| <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a>, and <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a> is used to prevent
 | |
| pointers intended for one extension from being redirected to a different
 | |
| extension.  For example, without the use of pointer types, an attacker 
 | |
| could still get access to pointer information in a system that included 
 | |
| both the <a href="fts3.html">FTS3</a> and the <a href="carray.html">CARRAY extension</a> using SQL like this:
 | |
| 
 | |
| </p><div class="codeblock"><pre>SELECT ca.value FROM t1, carray(t1,10) AS ca WHERE cx MATCH $pattern
 | |
| </pre></div>
 | |
| 
 | |
| <p>
 | |
| In the statement above, the FTS3 cursor pointer generated by the
 | |
| MATCH operator is send into the carray() table-valued function instead
 | |
| of its intended recipient snippet().  The carray() function treats the
 | |
| pointer as a pointer to an array of integers and returns each integer
 | |
| one by one, thus leaking the content of the FTS3 cursor object.  Since
 | |
| the FTS3 cursor object contains pointers to other objects, the statement
 | |
| above would be a pointer leak.
 | |
| 
 | |
| </p><p>
 | |
| Except, the statement above does not work, thanks to pointer types.
 | |
| The pointer generated by the MATCH operator has a type of "fts3cursor"
 | |
| but the carray() function expects to receives a pointer of type "carray".
 | |
| Because the pointer type on the <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> does not match
 | |
| the pointer type on the <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a> call, 
 | |
| <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a> returns NULL in carray() and thus signals
 | |
| the CARRAY extension that it has been passed an invalid pointer.
 | |
| 
 | |
| </p><h3 id="pointer_types_are_static_strings"><span>3.1.1. </span>Pointer types are static strings</h3>
 | |
| 
 | |
| <p>
 | |
| Pointer types are static strings, which ideally should be string literals
 | |
| embedded directly in the SQLite API call, not parameters passed in from
 | |
| other functions.  Consideration was given to using integer values as
 | |
| the pointer type, but static strings provides a much larger name space
 | |
| which reduces the chance of accidental type-name collisions between
 | |
| unrelated extensions.
 | |
| 
 | |
| </p><p>
 | |
| By "static string", we mean a zero-terminated array of bytes that is
 | |
| fixed and unchanging for the life of the program.  In other words, the
 | |
| pointer type string should be a string constant.
 | |
| In contrast, a "dynamic string" is a zero-terminated array of bytes
 | |
| that is held in memory allocated
 | |
| from the heap, and which must be freed to avoid a memory leak.
 | |
| Do not use dynamic strings as the pointer type string.
 | |
| 
 | |
| </p><p>
 | |
| Multiple commentators have expressed a desire to use dynamic strings
 | |
| for the pointer type, and to have SQLite take ownership of the type strings
 | |
| and to automatically free the type string
 | |
| when it has finished using it.  That design is rejected for the
 | |
| following reasons:
 | |
| 
 | |
| </p><ol>
 | |
| <li><p>
 | |
| The pointer type is not intended to be flexible and dynamic.  The
 | |
| pointer type is intended to be a design-time constant.  Applications
 | |
| should not synthesize pointer type strings at run-time.  Providing
 | |
| support for dynamic pointer type strings would lead developers
 | |
| to misuse the pointer-passing interfaces by creating run-time
 | |
| synthesized pointer type strings.  Requiring the pointer type strings
 | |
| to be static encourages developers to do the right thing by choosing
 | |
| fixed pointer type names at design-time and encoding those names
 | |
| as constant strings.
 | |
| 
 | |
| </p></li><li><p>
 | |
| All string values at the SQL level in SQLite are dynamic strings.  
 | |
| Requiring type strings to be static makes it difficult to 
 | |
| create an application-defined SQL function that
 | |
| can synthesize a pointer of an arbitrary type.  We do not want users
 | |
| to create such SQL functions, since such functions would compromise the
 | |
| security of the system.  Thus, the requirement to use static strings
 | |
| helps to defend that the integrity of the pointer-passing interfaces against
 | |
| ill-designed SQL functions.  The static string requirement is not
 | |
| a perfect defense, since a sophisticated programmer can code around
 | |
| it, and a novice program can simply take the memory leak.  But by
 | |
| stating that the pointer type string must be static, we hope to encourage
 | |
| developers who might otherwise use a dynamic string for the pointer type
 | |
| to think more carefully about the problem and avoid introducing
 | |
| security issues.
 | |
| 
 | |
| </p></li><li><p>
 | |
| Having SQLite take ownership of the type strings would impose a performance
 | |
| cost on all applications, even applications that do not use the 
 | |
| pointer-passing interfaces.  SQLite passes values around as instances
 | |
| of the <a href="c3ref/value.html">sqlite3_value</a> object.  That object has a destructor, which because
 | |
| of the fact that sqlite3_value objects are used for nearly everything, is
 | |
| invoked frequently.  If the destructor needs to check to see if there is
 | |
| a pointer type string that needs to be freed, that is a few extra CPU
 | |
| cycles that need to be burned on each call to the destructor.  Those
 | |
| cycles add up.  We would be willing to bear the cost of the extra CPU
 | |
| cycles if pointer-passing was a commonly used programming paradigm, but
 | |
| pointer-passing is rare, and so it seems unwise to impose a run-time cost
 | |
| on billions and billions of applications that do not use pointer passing
 | |
| just for convenience of a few applications that do.
 | |
| </p></li></ol>
 | |
| 
 | |
| <p>
 | |
| If you feel that you need dynamic pointer type strings in your application,
 | |
| that is a strong indicator that you are misusing the pointer-passing interface.
 | |
| Your intended use may be unsafe.
 | |
| Please rethink your design.  Determine if you really need to be passing
 | |
| pointers through SQL in the first place.  Or perhaps find a different
 | |
| mechanism other than the pointer-passing interfaces described by this
 | |
| article.
 | |
| 
 | |
| </p><h2 id="destructor_functions"><span>3.2. </span>Destructor Functions</h2>
 | |
| 
 | |
| <p>
 | |
| The last parameter to the <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> and
 | |
| <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> routines is a pointer to a procedure
 | |
| used to dispose of the P pointer once SQLite has finished with it.
 | |
| This pointer can be NULL, in which case no destructor is called.
 | |
| 
 | |
| </p><p>
 | |
| When the D parameter is not NULL, that means that ownership of the
 | |
| pointer is being transferred to SQLite.  SQLite will take responsibility
 | |
| for freeing resources associated with the pointer when it has finished
 | |
| using the pointer.  If the D parameter is NULL, that means that ownership
 | |
| of the pointer remains with the caller and the caller is responsible for
 | |
| disposing of the pointer.
 | |
| 
 | |
| </p><p>
 | |
| Note that the destructor function D is for the pointer value P, not for
 | |
| the type string T.  The type string T should be a static string with an
 | |
| infinite lifetime.
 | |
| 
 | |
| </p><p>
 | |
| If ownership of the pointer is passed into SQLite by providing a
 | |
| non-NULL D parameter to <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> or <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a>
 | |
| then the ownership remains with SQLite until the object is destroyed.
 | |
| There is no way to transfer ownership out of SQLite and back into the
 | |
| application again.
 | |
| 
 | |
| </p><h1 id="restrictions_on_the_use_of_pointer_values"><span>4. </span>Restrictions On The Use of Pointer Values</h1>
 | |
| 
 | |
| <p>
 | |
| The pointers that piggy-back on SQL NULL values using the
 | |
| <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a>, <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a>, and
 | |
| <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a> interface are transient and ephemeral.
 | |
| The pointers are never written into the database.  The pointers
 | |
| will not survive sorting.  The latter fact is why there is no
 | |
| sqlite3_column_pointer() interface, since it is impossible to
 | |
| predict whether or not the query planner will insert a sort operation
 | |
| prior to returning a value from a query, so it would be impossible to
 | |
| know if a pointer value inserted into a query by
 | |
| <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> or <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> would survive
 | |
| through to the result set.
 | |
| 
 | |
| </p><p>
 | |
| Pointer values must flow directly from their producer into their
 | |
| consumer, with no intermediate operators or functions.  Any transformation
 | |
| of a pointer value destroys the pointer and transforms the value into
 | |
| an ordinary SQL NULL.
 | |
| 
 | |
| </p><p>
 | |
| Both the pointer and the pointer type parameter to the
 | |
| <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a> and <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a> interfaces
 | |
| are "owned" by the caller.  In other words, the caller is responsible
 | |
| for ensuring that both values remain valid until after the last access
 | |
| via <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a>.
 | |
| 
 | |
| </p><h1 id="summary"><span>5. </span>Summary</h1>
 | |
| 
 | |
| <p>Key take-aways from this essay:
 | |
| 
 | |
| </p><ol>
 | |
| <li><p>
 | |
| The internet is an increasingly hostile place.  These day, developers
 | |
| should assume that attackers will find a way to execute arbitrary SQL 
 | |
| in an application.
 | |
| Applications should be designed to prevent the execution of arbitrary
 | |
| SQL from escalating into a more severe exploit.
 | |
| 
 | |
| </p></li><li><p>
 | |
| A few SQLite extensions benefit from passing pointers:
 | |
| </p><ul>
 | |
| <li>The <a href="fts3.html">FTS3</a> MATCH operator passes pointers into <a href="fts3.html#snippet">snippet()</a>,
 | |
|     <a href="fts3.html#offsets">offsets()</a>, and <a href="fts3.html#matchinfo">matchinfo()</a>.
 | |
| </li><li>The <a href="carray.html">carray table-valued function</a> needs to accept a pointer to
 | |
|     an array of C-language values from the application.
 | |
| </li><li>The <a href="https://sqlite.org/src/file/ext/misc/remember.c">remember() extension</a>
 | |
|     needs a pointer to a C-language integer variable in which to remember
 | |
|     the value it passes.
 | |
| </li><li>Applications need to receive a pointer to the "fts5_api" object in order
 | |
|     to add extensions, such as custom tokenizers, to the <a href="fts5.html">FTS5</a> extension.
 | |
| </li></ul>
 | |
| 
 | |
| </li><li><p>
 | |
| Pointers should <u>never</u> be exchanged by encoding them as some other
 | |
| SQL datatype, such as integers or BLOBs.  Instead, use the interfaces
 | |
| designed to facilitate secure pointer passing:
 | |
| <a href="c3ref/bind_blob.html">sqlite3_bind_pointer()</a>, <a href="c3ref/result_blob.html">sqlite3_result_pointer()</a>, and
 | |
| <a href="c3ref/value_blob.html">sqlite3_value_pointer()</a>.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The use of pointer-passing is an advanced technique that should be used
 | |
| infrequently and cautiously.  Pointer-passing should not be
 | |
| used haphazardly or carelessly.  Pointer-passing is a sharp tool 
 | |
| that can leave deep scars if misused.
 | |
| 
 | |
| </p></li><li><p>
 | |
| The "pointer type" string which is the last parameter to each of the
 | |
| pointer-passing interfaces should be a distinct, application-specific
 | |
| string literal that appears directly in the API call.  The pointer type
 | |
| should not be a parameter passed in from a higher-level function.
 | |
| </p></li></ol>
 | |
| 
 |