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>
|
|
|