c++ - 使 QString 数据字节无效

标签 c++ qt qstring

我使用 QString 来存储密码。更准确地说,我使用 QString 从 GUI 获取密码。 重点是,在密码使用/设备之后,我需要用密码使内部 QString 的数据字节无效(零),以将其从内存中完全消除。

这是我的调查:

  • QString 销毁后,它的数据在内存中保持非零;
  • 当我尝试修改 QString 以用零填充它时,它会触发写时复制习惯用法并为修改后的数据变体分配新内存。旧数据保持不变。即使我使用 QString::data() 方法也会发生同样的情况。不太确定为什么 - 可能是因为它返回的不是原始 char * 而是 QChar *;
  • QString::clear(), = "" 实际上执行与上述相同的 COW。

问:如何实现适当的 QString 清理以防止密码泄露?

最佳答案

我有两种绕过写时复制的可能方法。我已经尝试过它们并且它们似乎工作 - 没有使用 Qt Creator 的内存查看器,但我的代码中使用的隐式共享 QString 之后都指向相同的归零数据。

使用 constData()

Qt docs for QString::data() method 中所写:

For read-only access, constData() is faster because it never causes a deep copy to occur.

所以可能的解决方案是这样的:

QString str = "password";
QString str2 = str;
QChar* chars = const_cast<QChar*>(str.constData());
for (int i = 0; i < str.length(); ++i)
    chars[i] = '0';
// str and str2 are now both zeroed

这是 const_cast 的合法使用,因为底层数据并不是真正的 const,所以这里没有未定义的行为。

使用迭代器

来自Qt docs for implicit sharing :

An implicitly shared class has control of its internal data. In any member functions that modify its data, it automatically detaches before modifying the data. Notice, however, the special case with container iterators; see Implicit sharing iterator problem.

那么让我们转到描述 this iterator problem 的部分:

Implicit sharing has another consequence on STL-style iterators: you should avoid copying a container while iterators are active on that container. The iterators point to an internal structure, and if you copy a container you should be very careful with your iterators. E.g.:

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
    Now we should be careful with iterator i since it will point to shared data
    If we do *i = 4 then we would change the shared instance (both vectors)
    The behavior differs from STL containers. Avoid doing such things in Qt.
*/

a[0] = 5;
/*
    Container a is now detached from the shared data,
    and even though i was an iterator from the container a, it now works as an iterator in b.
*/

据我了解,基于上述文档片段,您应该能够利用迭代器的这种“错误用法”来使用迭代器操作您的原始字符串,因为它们不会触发写时复制。在任何复制发生之前“拦截”begin()end() 很重要:

QString str = "password";
QString::iterator itr = str.begin();
QString::iterator nd = str.end();
QString str2 = str;

while (itr != nd)
{
    *itr = '0';
    ++itr;
} // str and str2 still point to the same data and are both zeroed

关于c++ - 使 QString 数据字节无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44913102/

相关文章:

c++ - 绘图框架

c++ - 返回带有 bool 结果标志的值的标准模板

c++ - 使用QScriptEngine计算计算

c++ - 为什么在我们使用指针之前对数组的引用不起作用?

performance - 如何更改 QListWidget 实现以提高性能?

c++ - 将 QString 十六进制转换为 ASCII 值

c++ - QString,去掉标签和内容?

c++ - 通过内容访问 QVector 元素索引

c++ - gcc的 "__builtin_popcount"是怎么工作的?

c++ - boost C++ 和 Windows CE 6.0