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

Underscores are unnecessarily escaped in db_mysql #20153

Closed
hokamoto opened this issue Aug 4, 2022 · 10 comments · Fixed by #20164
Closed

Underscores are unnecessarily escaped in db_mysql #20153

hokamoto opened this issue Aug 4, 2022 · 10 comments · Fixed by #20164
Assignees

Comments

@hokamoto
Copy link
Contributor

hokamoto commented Aug 4, 2022

Architecture

No response

Operating System

No response

Disk

No response

Memory

No response

CPU Cores

No response

Internet Connection

No response

What is your web browser?

No response

Device

No response

What happened?

dbQuote() has been modified to escape special characters in #15234. Underscore(_) is a special character only in pattern-matching contexts for LIKE operator, so it should not be escaped anywhere else. Underscores in inserted values or expressions for WHERE clause without LIKE operator are unnecessarily escaped due to this bug.
https://dev.mysql.com/doc/refman/8.0/en/string-literals.html

Current Standard Output Logs

import db_mysql
echo dbQuote("SELECT * FROM foo WHERE col1 = 'bar_baz'")
echo dbQuote("SELECT * FROM foo WHERE col1 LIKE '%bar_baz%'")

'SELECT * FROM foo WHERE col1 = \'bar\_baz\''
'SELECT * FROM foo WHERE col1 LIKE \'%bar\_baz%\''

Expected Standard Output Logs

'SELECT * FROM foo WHERE col1 = \'bar_baz\''
'SELECT * FROM foo WHERE col1 LIKE \'%bar\_baz%\''

Possible Solution

  1. Escape underscores only for LIKE operators
  2. Do not escape underscores

For example, PHP does not seem to escape underscores.
https://www.php.net/manual/ja/mysqli.real-escape-string.php#46339

Additional Information

This issue could happen for percent signs (%), but it was fixed for percent sings in 8e181cb

@hokamoto
Copy link
Contributor Author

hokamoto commented Aug 4, 2022

$ nim -v
Nim Compiler Version 1.6.6 [Linux: amd64]
Compiled at 2022-05-05
Copyright (c) 2006-2021 by Andreas Rumpf

git hash: 0565a70eab02122ce278b98181c7d1170870865c
active boot switches: -d:release

@ringabout ringabout self-assigned this Aug 5, 2022
ringabout added a commit that referenced this issue Aug 5, 2022
Varriount added a commit that referenced this issue Aug 5, 2022
* fixes #20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
metagn pushed a commit to metagn/Nim that referenced this issue Aug 12, 2022
…g#20164)

* fixes nim-lang#20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
ringabout added a commit that referenced this issue Aug 15, 2022
* Improve error message for `strutils.addf` (#20157)

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>

* fixes #20153; do not escape `_` for mysql [backport] (#20164)

* fixes #20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>

* [minor] don't find `"Hint: gc"` for action (#20170)

* fixes links in the readme (#20167)

* update the docs of arc following up #19749 (#19752)

Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>

* fixes broken ssl tests (#20181)

* bootstrap the compiler with nimPreviewSlimSystem (#20176)

* bootstrap the compiler with nimPreviewSlimSystem

* threads

* docs: fix some spelling errors (#19816)

* docs: fix some spelling errors

* contributing: fix spelling error

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>

* Update contributing.md

* Update intern.md

* Update manual.md

* Update manual_experimental_strictnotnil.md

* Update nimgrep_cmdline.txt

* Update pegdocs.txt

* Update testament.md

* Update tut1.md

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>

* Build compiler with --noNimblePath (#20168)

- Fixes #18840

* help our poor CI; don't run CI on other branches for push (#20184)

* fix broken runnableExamples for getWeeksInIsoYear (#20193)

Based on what I understand from [Wikipedia](https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year), 2001 does not have 53 weeks, but 2004, 2009, 2015, 2020 do. The years 2000 and 2001 seem to be copy pasted from the `getDaysInYear` example above. The result of `getWeeksInIsoYear` also seem to match up with Wikipedia.

That means these runnableExamples were never tested. Why is this the case? I only discovered this in #20091.

* improve deprecation error messages (#20197)

* Show beatutiful html instead of ugly markdown preview (#20196)

* closes #6559; add testcase (#20200)

* CI upgrade to ubuntu-20.04 (#20182)

* CI upgrade to ubuntu-20.04 

The ubuntu-18.04 environment is deprecated, consider switching to ubuntu-20.04(ubuntu-latest), or ubuntu-22.04 instead. For more details see actions/runner-images#6002

* Update azure-pipelines.yml

* Markdown code blocks part 4 (#20189)

No logic was added, just 8 more files have been migrated.

* closes #15316; add testcase (#20213)

* add version-1-6 and version-1-2 to triggered branches (#20214)

* add version-1-6 and version-1-2 to triggered branches

* Update .github/workflows/ci_packages.yml

* use quote

* closes #12955; add testcase (#20223)

* add more

Co-authored-by: konsumlamm <44230978+konsumlamm@users.noreply.github.com>
Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
Co-authored-by: flywind <43030857+xflywind@users.noreply.github.com>
Co-authored-by: ee7 <45465154+ee7@users.noreply.github.com>
Co-authored-by: Ivan Yonchovski <yyoncho@users.noreply.github.com>
Co-authored-by: metagn <metagngn@gmail.com>
Co-authored-by: Andrey Makarov <ph.makarov@gmail.com>
narimiran pushed a commit that referenced this issue Aug 23, 2022
* fixes #20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
(cherry picked from commit 3bd935f)
@bung87
Copy link
Collaborator

bung87 commented Sep 12, 2022

that's weird example for use case of dbQuote, dbQuote is used to quote single param to replace placeholder, here is use for whole sql, the 8e181cb wasn't correct fix c16ee37#r44209990 in that use case should be %?% then quote param, not put user source value to it directly. for this one fix should take Solution 1 IMO.

@hokamoto
Copy link
Contributor Author

hokamoto commented Sep 13, 2022

As you pointed out, similar features in other languages are used for escaping parameters, not for escaping entire SQL statements, but there is a reason I mentioned the 'weird' example. dbFormat() function automatically performs dbQuote() on all parameters.
https://github.com/nim-lang/Nim/blob/devel/lib/impure/db_mysql.nim#L145
This causes a problem when the value for INSERT statements contain _ (underscore) character. I admit that the SELECT statement was not the best example, but in any case, dbQuote() was causing problems for INSERT statements.

The actual code of mine was as follows. Broken values got inserted when original_filepath contains _ (underscore) characters. This code worked before.

db.exec(sql"INSERT INTO files (hash, original_filepath, width, height) VALUES (?, ?, ?, ?)", hash, original_filepath, width, height)

@bung87
Copy link
Collaborator

bung87 commented Sep 13, 2022

so % and _ should quote when use like, need revert the revert waiting for correct fix and correct the test file that's misleading users.

@hokamoto
Copy link
Contributor Author

hokamoto commented Sep 13, 2022

I disagree with reverting this fix. If someone can implement Solution 1 correctly, I would welcome it (but I think it would be difficult), but Solution 2 recently made should not be reverted. Since exec() automatically calls dbQuote(), this problem can't be avoided by tweaking the caller code when parameter binding is used. In other words, there is no way to insert a value containing underscores if we revert the fix.

By updating this library recently without realizing that the escaping of underscores had been added, I kept getting broken values inserted into my database.

@hokamoto
Copy link
Contributor Author

hokamoto commented Sep 13, 2022

Or, dbFormat() should stop calling dbQuote() automatically. Leaving it up to the caller to decide whether to escape the value to be bound is an option. That is acceptable to me.

@bung87
Copy link
Collaborator

bung87 commented Sep 13, 2022

I disagree with reverting this fix. If someone can implement Solution 1 correctly, I would welcome it (but I think it would be difficult), but Solution 2 recently made should not be reverted. Since exec() automatically calls dbQuote(), this problem can't be avoided by tweaking the caller code when parameter binding is used. In other words, there is no way to insert a value containing underscores if we revert the fix.

By updating this library recently without realizing that the escaping of underscores had been added, I kept getting broken values inserted into my database.

that's may not difficult than you think , we have parsesql library(maybe just use string find to detect like statement), and as you concerns, just waiting correct fix. and sql query string should prefix with sql , plain string is wrong. so there's space tweaking the sql, for users use plain string they already taken risk.

@hokamoto
Copy link
Contributor Author

hokamoto commented Sep 13, 2022

exec() takes a SqlQuery argument, so I believe we can't pass a string
https://github.com/nim-lang/Nim/blob/devel/lib/impure/db_mysql.nim#L160

Am I missing something? In the following code, when the original_path has underscores in it, is there any way to correctly INSERT this value into the database even after reverting the fix?

db.exec(sql"INSERT INTO files (hash, original_filepath, width, height) VALUES (?, ?, ?, ?)", hash, original_filepath, width, height)

@bung87
Copy link
Collaborator

bung87 commented Sep 13, 2022

exec() takes a SqlQuery argument, so I believe we can't pass a string https://github.com/nim-lang/Nim/blob/devel/lib/impure/db_mysql.nim#L160

Am I missing something? In the following code, when the original_path has underscores in it, is there any way to correctly INSERT this value into the database even after reverting the fix?

db.exec(sql"INSERT INTO files (hash, original_filepath, width, height) VALUES (?, ?, ?, ?)", hash, original_filepath, width, height)

so there's no worry about, we can detect like statement and decide whether quote % and _ or not. I mean revet will comming along with correct fix in single PR.

@hokamoto
Copy link
Contributor Author

I got it. I agree with you.

ringabout added a commit that referenced this issue Dec 1, 2022
* fixes #20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
capocasa pushed a commit to capocasa/Nim that referenced this issue Mar 31, 2023
…g#20164)

* fixes nim-lang#20153; do not escape `_` for mysql

* add a test

* Update db_mysql.nim

* Update tdb_mysql.nim

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants