作者godfat (godfat 真常)
看板java
标题[J2SE] string literal
时间Thu Jan 25 02:38:36 2007
我只能说我真的感到很吃惊,因为我从来没想过可能会有这种事情
尤其又是在 Java 这种强调安全的程式语言当中,居然可以玩这种花招
这是在 comp.lang.c++.moderated 看来的(咦?)
topic 是 The D Programming Language(咦咦?)
内容是在讲 Java 的 string literal(咦咦咦?)
well, 我不太会找连结,有人愿意的话可以帮忙提供个 link
这边就引用一些来自那里的文章,希望作者不会介意
(顺便补上一点翻译好了,不过我只翻重点)
Niklas Matthies wrote:
> Well, it depends what one considers "basic". It's possible in Java to
> have the statement
> System.out.println("Hello, world!");
这行 Java 叙述,是有可能-
> output "Suprise!" (or any other arbitrary string), by appropriate
> preceding code.
印出 "Suprise!"(或是其他任何的字串),藉由印出字串前的一些手段。
> (This is because string literals within a class are guaranteed to be
> shared, so a different occurrence of "Hello, world!" in the source
> code can be used to manipulate the contents of that shared String
> object.)
因为字面字串是被共享的。
有人问起了这怎麽可能?(How is it possible? - by Andrei Alexandrescu)
於是 Niklas Matthies 就提供了 code...
我做了一点修改,增加一些其他人提供的例子
class Test
{
public static void main(String[] args) throws Exception
{
java.util.HashSet<String> set = new java.util.HashSet<String>();
set.add("Hello, World!");
doEvil();
set.add("Hello, World!");
System.out.println(set);
// prints "[Surprise!, Surprise!]"
System.out.println("Hello, World!");
// prints "Surprise!"
System.out.println("Hello, World!".indexOf('H'));
// prints -1
String s = new String("Hello, World!");
System.out.println(s);
// prints "Surprise!"
}
static void doEvil() throws Exception
{
String s = "Surprise!";
String hw = "Hello, World!";
setField(hw, "value", s.toCharArray());
setField(hw, "count", Integer.valueOf(s.length()));
setField(hw, "hash", Integer.valueOf(0));
}
static void setField(Object object, String name, Object value)
throws Exception
{
java.lang.reflect.Field
field = object.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(object, value);
}
}
另外也有人说,有个网站上也有一篇文章指出这个问题
(做了一点编辑上的修改)
peter koch larsen
Andrei Alexandrescu (See Website For Email) skrev:
> I didn't know that! How is it possible? Got code? Heck, it's not
> possible in many C and C++ implementations - they put constant strings
> in read-only pages.
cheers! Andrei,
I accidently fell over an article called something like
"hi there".equals("cheers !") == true
and skimming the article shows that this is exactly the article you
requested. It is referenced at Kevlin Heeney'(?)s web (curbralan?), and
I believe it was an article from Artima. Anyway, a quick google should
get you home no sweat.
hi there
Peter
有兴趣的人可以去 google 看看,我是懒得看了
而我因为好奇而稍微翻了一下 Java API reflection 的部份,
大概知道是发生了什麽事情。上面红色标起来的那段程式是重点。
他找到了 string literal 的储存所在地,然後修改那段记忆体里的东西,
於是,Surprise!
重点就是,Java 为什麽允许这样的修改?
Niklas Matthies 说这是为了使程式不用在 debugging mode 下也能进行 debug.
而,如果这个程式真的有安全性问题的话,应该要使用 SecurityManager
来阻止这件事发生,也就是使得那行
field.setAccessible(true); 失败
Niklas Matthies
On 2006-12-15 13:23, James Kanze wrote:
> In the case of Java, the problem concerning literals may be the
> most shocking, externally, but the fact that you can modify a
> String after having passed it to another subsystem is far more
> serious, since it undermines many of Java's security measures.
No, it doesn't, because a security-conscious application will
run under a SecurityManager that will prevent such accesses
(the setAccessible() call will fail).
The motivation for enabling such accesses is of course for use by a
debugger without causing the debugging-enabled Java implementation to
become non-conformant.
-- Niklas Matthies
what a surprise!
简言之,reflection 不要乱用,SecurityManager 有时候要考虑用一下。
--
Hear me exalted spirits. Hear me, be you gods or devils, ye who hold
dominion here:
I am a wizard without a home. I am a wonderer seeking refuge.
Sacrifice
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.135.28.18
※ 编辑: godfat 来自: 220.135.28.18 (01/25 15:47)