📜  Python中的 str.format() 中的漏洞(1)

📅  最后修改于: 2023-12-03 15:19:26.367000             🧑  作者: Mango

Python中的 str.format() 中的漏洞

当我们在使用 Python 中的 str.format() 函数时,如果字符串中的格式化参数与传入的参数个数不匹配,就会报错,例如:

>>> name = "Alice"
>>> age = 23
>>> "My name is {}, and I am {} years old.".format(name, age)
'My name is Alice, and I am 23 years old.'
>>> "My name is {}, and I am {} years old.".format(name)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

这种情况下,我们通常会使用索引或者命名参数来解决:

>>> "My name is {0}, and I am {1} years old.".format(name, age)
'My name is Alice, and I am 23 years old.'
>>> "My name is {name}, and I am {age} years old.".format(name=name, age=age)
'My name is Alice, and I am 23 years old.'

然而,在使用 str.format() 时还存在另外一个漏洞:占位符未被填充时会抛出异常。例如:

>>> "{}{}{}{}".format("a")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range

这时候程序会抛出 IndexError 异常,因为字符串中有 4 个占位符,但只传递了一个参数。

为了避免这个漏洞,我们通常会在占位符中加一些默认值:

>>> "{0}{1}{2}{3}".format("a", "", "", "")
'a'

不过,这样做有些繁琐。幸运的是,Python 3.8 引入了一种新的格式化字符串语法 f-string,语法类似于模板字符串,并且可以在占位符中直接使用变量名:

>>> f"My name is {name}, and I am {age} years old."
'My name is Alice, and I am 23 years old.'
>>> f"{name}{' '*3}{age}"
'Alice   23'

因为 f-string 没有使用反括号 {},所以不存在漏洞问题。

总结:

  • 在使用 str.format() 时,需要注意占位符与传入参数的个数匹配;
  • 如果占位符未被正确填充,程序会抛出 IndexError 异常;
  • 在占位符中加入一些默认值可以避免这个漏洞;
  • 在 Python 3.8 中引入了 f-string,可以避免这个漏洞。