summaryrefslogtreecommitdiffstats
path: root/www/bindptr.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--www/bindptr.html596
1 files changed, 596 insertions, 0 deletions
diff --git a/www/bindptr.html b/www/bindptr.html
new file mode 100644
index 0000000..4d62397
--- /dev/null
+++ b/www/bindptr.html
@@ -0,0 +1,596 @@
+<!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;
+}
+var antiRobot = 0;
+function antiRobotGo(){
+if( antiRobot!=3 ) return;
+antiRobot = 7;
+var j = document.getElementById("mtimelink");
+if(j && j.hasAttribute("data-href")) j.href=j.getAttribute("data-href");
+}
+function antiRobotDefense(){
+document.body.onmousedown=function(){
+antiRobot |= 2;
+antiRobotGo();
+document.body.onmousedown=null;
+}
+document.body.onmousemove=function(){
+antiRobot |= 2;
+antiRobotGo();
+document.body.onmousemove=null;
+}
+setTimeout(function(){
+antiRobot |= 1;
+antiRobotGo();
+}, 100)
+antiRobotGo();
+}
+antiRobotDefense();
+</script>
+<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">&#x25ba;</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 = "&#x25bc;";
+} else {
+sub.style.display = "none";
+mk.innerHTML = "&#x25ba;";
+}
+}
+</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> &rarr;
+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> &rarr;
+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> &rarr;
+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><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>
+<p align="center"><small><i>This page last modified on <a href="https://sqlite.org/docsrc/honeypot" id="mtimelink" data-href="https://sqlite.org/docsrc/finfo/pages/bindptr.in?m=0313c341708d7be8d">2022-10-07 10:23:26</a> UTC </small></i></p>
+