伪造一个字符串引用

本文关键字:一个 字符串 引用 伪造 | 更新日期: 2023-09-27 18:08:47

是否有可能为以下方法的调用者制作一个字符串引用并将其作为token传递,以便该方法返回true?(假设调用方没有使用反射从静态字段获取字符串引用)

class GuessTheSecret
{
    private static readonly string Secret = new string("Secret".ToCharArray());
    public static bool IsCorrect(string token)
    {
        return object.ReferenceEquals(token, Secret);
    }
}

伪造一个字符串引用

No。您必须向调用者公开静态实例。引用相等意味着它们是完全相同的对象。除非有访问该特定对象的方法,否则不能有另一个对象引用相同的内存。如果您要使用相等操作符,这将是不同的,因为string重载它来执行值相等而不是引用相等。

另一方面,如果您将静态实例值设置为常量,则可以(通过使用该常量)拥有与静态实例相等的引用。这是因为字符串字面值在整个代码中被存储和共享,这意味着所有相同的字符串字面值具有相同的引用。 例如,

class GuessTheSecret
{
    private static readonly string Secret = "Secret";
    public static bool IsCorrect(string token)
    {
        return object.ReferenceEquals(token, Secret);
    }
}
Console.WriteLine( GuessTheSecret.IsCorrect( "Secret" ) );

将输出True

我认为是"这取决于",基本上取决于调用者是否传递与您的字符串实习的相同程序集字符串。

原因如下:

ReferenceEquals做你想的,比较内存位置,而不是对象值(MSDN):

通过调用ReferenceEquals方法,您可以看到这两个字符串实际上在内存中引用相同的对象。

c#有一个叫做字符串实习的特性,Eric Lippert说:

如果在一个编译单元中有两个相同的字符串字面值,那么我们生成的代码将确保CLR仅为程序集中该字面值的所有实例创建一个字符串对象。这种优化称为"字符串实习"。

然而,从同一篇文章中,默认情况下并不能保证每个字符串都有实习:

如果你正在用c#编写一个编译器,或者有一些其他的应用程序,在这些应用程序中,你觉得确保数千个相同的字符串不会消耗大量的内存是值得的,你可以强制运行时用string来实习你的字符串。实习方法。

相反,如果你不喜欢毫无理由的实习,你可以通过CompilationRelaxation属性强制运行时关闭程序集中的所有字符串实习。

无论你想要完成什么,你目前的实现看起来充其量是不可靠的——我得考虑重新考虑你在做什么。