форматирования строк:
* f-строки
* .format
* %
Мы их часто используем для формирования текста, как человеко-читаемого, так и понятного компьютеру.
Если с формированием текста для человека скорее всего больших проблем нет. В худшем случае человеку придется приложить дополнительные усилия, чтобы понять, что он видит.
То с формированием текста для компьютера мы рискуем получить строку, которую он просто не сможет понять или поймет неверно. В том числе это может привести к порче или утечке данных.
Компьютер ожидает, что обрабатываемый текст будет оформлен согласно определенным правилам и вы не можете просто так вставить туда произвольную строку не нарушив при этом структуру текста.
Речь идет о формировании SQL, XML, HTML, JSON, консольной команды, URL, регулярных выражений и ещё кучи различных типов строк.
Как правило такая проблема решается одним из двух способов:
1. Ручное экранирование данных
2. Вызов специальных библиотечных методов, подставляющих данные безопасно.
Как правило лучше выбирать второй способ, так он проще и оставляет меньше шансов ошибиться.
Рассмотрим примеры.
1. SQL
Допустим вы хотите прочитать данные из БД и пишете такой запрос:
cur.execute(f"SELECT * FROM users WHERE login = '{somelogin}'")
Он будет работать в каких-то случаях и обязательно сломается, если переменная somelogin будет содержать, например, кавычку.
В некоторых случаях это может привести к исполнению произвольного SQL кода.
Замена f-строки на .format или форматирование через % ничего не изменит.
Правильно тут было бы сделать так (использовать тут ? или другой символ зависит от вашей СУБД):
cur.execute("SELECT * FROM users WHERE login = ?", (somelogin,))
2. HTTP
Если вы делаете GET запрос, вы можете напистаь такой код:
requests.get(f"http://site.com?search={query}")
Он будет работать некорректно если переменная query, например, содержит знаки &?
Правильно написать так:
requests.get("http://site.com", params={"search": query})
3. Shell
Следующий код сломается если имя папки содержит пробел ил точку с запятой и может привести к исполнению произвольных команд.
subprocess.run(f"ls {dirname}")
Его стоит заменить на
subprocess.run(["ls", dirname])
4. HTML
В случае подстановки данных в HTML стоит воспользоваться специальными шаблонизаторами. Например, jinja.
Доп материалы:
* https://xkcd.ru/327/
* https://ru.wikipedia.org/wiki/Внедрение_SQL-кода
* https://ru.wikipedia.org/wiki/Межсайтовый_скриптинг
#faq
Ну наконец свою пасту написал\
Ничего нового не узнал после прочтения
только в первом subprocess.run ты shell=True забыл. в позиксах без него работать не будет.
а если надо добавить имя таблицы из переменной, тоже можно '?' использовать? или . format. у меня просто с? не получилось в запрос имя таблицы воткнуть из переменной
Надо бы такие пасты собирать в какую-то общую базу,
имя таблицы в запрос динамически подставлять практически никогда не надо
пойду канал создам
Лучше подскажи чем можно сделать мультиязычность в программе, без лишнего гемора, или уже придётся писать свою библиотеку?
да gettext какой-то гемор как по мне
де-факто стандарт
у меня прост имя таблицы это id чата, чтоб различались они для каждого чата своя таблица. Лучше не придумала ничего:(
сделать одну таблицу, не?
Ужасно. Почему не одна таблица?
Даже удивительно что тут нет os.path) Моя личная боль urljoin - вроде и юзаю не первый месяц, но тупые ошибки появляются)
пора тебе открыть для себя нормальные формы.
это немного другой кейс
Мм ну тоже верно
Отношения в скл гугли
Обсуждают сегодня