Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: SQL statement expansion for plugin db_write hook #4090

Merged
merged 4 commits into from
Oct 10, 2020

Conversation

m-schmoock
Copy link
Collaborator

@m-schmoock m-schmoock commented Sep 24, 2020

I discovered this accidentally when using the tests/plugins/dblog.py
plugin on another testcase: tests/test_connection.py::test_fail_unconfirmed
There the plugin/hook crashes because it can't execute the statement:

{
  "jsonrpc": "2.0",
  "id": 34,
  "error": {
    "code": -32600,
    "message": "Error while processing db_write: unrecognized token: \"174WHERE\"",
    "traceback": "Traceback (most recent call last):\n  File \"/home/will/projects/lightning.git/contrib/pyln-client/pyln/client/plugin.py\", line 535, in _dispatch_request\n    result = self._exec_func(method.func, request)\n  File \"/home/will/projects/lightning.git/contrib/pyln-client/pyln/client/plugin.py\", line 520, in _exec_func\n    return func(*ba.args, **ba.kwargs)\n  File \"/home/will/projects/lightning.git/tests/plugins/dblog.py\", line 45, in db_write\n    plugin.conn.execute(c)\nsqlite3.OperationalError: unrecognized token: \"174WHERE\"\n"
  }
}

I used the following change to have the testcase execute the plugin:

diff --cc tests/test_connection.py
index 02780a233,02780a233..76789afa4
--- a/tests/test_connection.py
+++ b/tests/test_connection.py
@@@ -2351,8 -2351,8 +2351,11 @@@ def test_restart_many_payments(node_fac
  def test_fail_unconfirmed(node_factory, bitcoind, executor):
      """Test that if we crash with an unconfirmed connection to a known
      peer, we don't have a dangling peer in db"""
++    dbfile = os.path.join(node_factory.directory, "dblog.sqlite3")
++    opts={'plugin': os.path.join(os.getcwd(), 'tests/plugins/dblog.py'), 'dblog-file': dbfile}
++
      # = is a NOOP disconnect, but sets up file.
--    l1 = node_factory.get_node(disconnect=['=WIRE_OPEN_CHANNEL'])
++    l1 = node_factory.get_node(options = opts, disconnect=['=WIRE_OPEN_CHANNEL'])
      l2 = node_factory.get_node()
 
      # First one, we close by mutual agreement.

Update: I pulled in @cdecker changes from #4092 that fixes this for another location and adds a TEST_CHECK_DBSTMTS=1 option and a Travis Job so this does not happen again.

@cdecker
Copy link
Member

cdecker commented Sep 24, 2020

This has been in the codebase for quite some time, since 50ff0b2, but is only triggered when we run a plugin that uses the db_write hook. I think it must be that the query gets parsed and executed correctly as long as we use prepared statements where the parser does not combine the ? placeholder with the WHERE that immediately follows it. During the expansion for the plugin we then perform a string replacement where the timestamp gets juxtaposed to the WHERE which is no longer syntactically valid, which then causes any attempt to execute the expanded statement to fail.

Impacted RPC calls (including any plugins that make use of these calls):

  • reserveinputs
  • fundpsbt if a reservation was specified which is true
  • utxopsbt same as fundpsbt
  • sendpsbt

So the crash is triggered only if a) we have a db_write hook plugin, b) the plugin crashes while trying to parse/execute the statement and c) call any of the above RPC calls. This is pretty much only the dblog.py plugin.

cdecker added a commit to cdecker/lightning that referenced this pull request Sep 24, 2020
This can be used to find instances of unparseable expanded SQL statements like
the one fixed in ElementsProject#4090
cdecker added a commit to cdecker/lightning that referenced this pull request Sep 24, 2020
This can be used to find instances of unparseable expanded SQL statements like
the one fixed in ElementsProject#4090
I discovered this accidentally when using the `tests/plugins/dblog.py`
plugin on another testcase: tests/test_connection.py::test_fail_unconfirmed

There the plugin/hook crashes because it can't execute the statement:
```json
{
  "jsonrpc": "2.0",
  "id": 34,
  "error": {
    "code": -32600,
    "message": "Error while processing db_write: unrecognized token: \"174WHERE\"",
    "traceback": "Traceback (most recent call last):\n  File \"/home/will/projects/lightning.git/contrib/pyln-client/pyln/client/plugin.py\", line 535, in _dispatch_request\n    result = self._exec_func(method.func, request)\n  File \"/home/will/projects/lightning.git/contrib/pyln-client/pyln/client/plugin.py\", line 520, in _exec_func\n    return func(*ba.args, **ba.kwargs)\n  File \"/home/will/projects/lightning.git/tests/plugins/dblog.py\", line 45, in db_write\n    plugin.conn.execute(c)\nsqlite3.OperationalError: unrecognized token: \"174WHERE\"\n"
  }
}
```

Changelog-Fixed: plugin: Regression with SQL statement expansion that could result in invalid statements being passed to the `db_write` hook.
@m-schmoock
Copy link
Collaborator Author

m-schmoock commented Sep 25, 2020

@cdecker I pulled in your commits from #4092 and fixed the missing generated SQL files for NO_PYTHON of commit 3942e67 that failed job0.

@m-schmoock m-schmoock changed the title fix: broken SQL statement in wallet db_set_utxo fix: SQL statement expansion for plugin db_write hook Sep 25, 2020
@jsarenik
Copy link
Collaborator

utACK 9b02c78

@cdecker
Copy link
Member

cdecker commented Oct 6, 2020

ACK 9b02c78

@rustyrussell rustyrussell merged commit ad049c3 into ElementsProject:master Oct 10, 2020
rustyrussell pushed a commit that referenced this pull request Oct 10, 2020
This can be used to find instances of unparseable expanded SQL statements like
the one fixed in #4090
@m-schmoock m-schmoock deleted the fix/sql_db_set_utxo branch December 12, 2020 13:39
vibhaa pushed a commit to spider-pcn/lightning that referenced this pull request Mar 24, 2021
This can be used to find instances of unparseable expanded SQL statements like
the one fixed in ElementsProject#4090
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants