- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这是我的代码:
String str = "just_a_string";
System.out.println("]" + str + "[");
System.out.println("]" + str.replace("", "") + "[");
System.out.println("]" + str.substring(5) + "[");
System.out.println("]" + str.substring(5).replace("", "") + "[");
System.out.println("]" + str.substring(3, 8) + "[");
System.out.println("]" + str.substring(3, 8).replace("", "") + "[");
System.out.println("]" + "sdajndan".substring(5).replace("", "") + "[");
这是输出
05-09 19:09:20.570: I/System.out(23801): ]just_a_string[
05-09 19:09:20.570: I/System.out(23801): ]just_a_string[
05-09 19:09:20.570: I/System.out(23801): ]a_string[
05-09 19:09:20.570: I/System.out(23801): ]a_s[ **
05-09 19:09:20.570: I/System.out(23801): ]t_a_s[
05-09 19:09:20.570: I/System.out(23801): ]t_[ **
05-09 19:09:20.570: I/System.out(23801): ][ **
显然,标有**的行是意想不到的。
此问题发生在我的 Android 手机 A(LG P920 Optimus 3D,Android 2.3.3)上。当我在我的 Android 手机 B(LG E720 Optimus Chic,Android 2.2)上进行测试时,它停止了。我猜它会进入无限循环。
我已经在使用 Java 1.5
和 1.6
的两部手机上进行了测试。两者分别导致相同的行为。
我还在我的同一个 Eclipse 上用 Java 项目测试了 1.5
、1.6
和 1.7
。正如预期的那样,他们的所有输出都是正确的。
我想知道这可能是针对字符串的 backing array 实现 String.replace(“”, “”)
的设备特定问题.
你能帮我测试一下你的设备吗?
谁能给我String.replace(CharSequence, CharSequence)
方法的Android源代码? (就像 docjar 中的一样)
非常感谢!
我稍微修改了代码,所以它也可以在Android设备上显示。 (无论如何都是相同的代码)。
在我的手机 A 和手机 B 上进行了测试。行为仍然相同,如上所述。
package com.example.testprojectnew;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
String output_text = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String str = "just_a_string";
process("1]" + str + "[");
process("2]" + str.replace("", "") + "[");
process("3]" + str.substring(5) + "[");
process("4]" + str.substring(5).replace("", "") + "[");
process("5]" + str.substring(3, 8) + "[");
process("6]" + str.substring(3, 8).replace("", "") + "[");
process("7]" + "sdajndan".substring(5).replace("", "") + "[");
output_text = output_text.concat("\n\nLines (1 & 2), (3 & 4), (5 & 6), should be the same.");
((TextView) findViewById(R.id.a_string)).setText(output_text);
}
private void process(String str) {
System.out.println(str);
output_text = output_text.concat(str).concat("\n");
}
}
最佳答案
感谢@izht 提供 source code 的链接.我已经找到了关于这个问题的错误。
这只发生在字符串的 backing array 时。具有与实际字符串不同(更长)的值。特别是,当 String.offset
(私有(private)变量)大于零时。
修复方法如下:
public String replace(CharSequence target, CharSequence replacement) {
if (target == null) {
throw new NullPointerException("target == null");
}
if (replacement == null) {
throw new NullPointerException("replacement == null");
}
String targetString = target.toString();
int matchStart = indexOf(targetString, 0);
if (matchStart == -1) {
// If there's nothing to replace, return the original string untouched.
return this;
}
String replacementString = replacement.toString();
// The empty target matches at the start and end and between each character.
int targetLength = targetString.length();
if (targetLength == 0) {
int resultLength = (count + 2) * replacementString.length();
StringBuilder result = new StringBuilder(resultLength);
result.append(replacementString);
// for (int i = offset; i < count; ++i) { // original, bug
for (int i = offset; i < (count + offset); ++i) { // fix
result.append(value[i]);
result.append(replacementString);
}
return result.toString();
}
StringBuilder result = new StringBuilder(count);
int searchStart = 0;
do {
// Copy characters before the match...
result.append(value, offset + searchStart, matchStart - searchStart);
// Insert the replacement...
result.append(replacementString);
// And skip over the match...
searchStart = matchStart + targetLength;
} while ((matchStart = indexOf(targetString, searchStart)) != -1);
// Copy any trailing chars...
result.append(value, offset + searchStart, count - searchStart);
return result.toString();
}
我不确定为什么 Android 必须以这种方式更改(并且错误地更改)replace()
。原始的 Java 实现没有这个问题。
顺便问一下,现在怎么样了?我能用它做什么? (除非格外小心地使用 replace()
,否则就扔掉我的 Android 手机 :-/)
顺便说一句,我很确定我的 LG E720 Optimus Chic (Android 2.2) 使用的源代码与 that one 不同。 .它会在 String.replace()
上用 空 目标字符串停止(怀疑是无限循环)。最近我发现它抛出这个错误信息:
05-10 16:41:13.155: E/AndroidRuntime(9384): FATAL EXCEPTION: main
05-10 16:41:13.155: E/AndroidRuntime(9384): java.lang.OutOfMemoryError
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:97)
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:157)
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.StringBuilder.append(StringBuilder.java:217)
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.String.replace(String.java:1497)
05-10 16:41:13.155: E/AndroidRuntime(9384): at com.example.testprojectnew.MainActivity.onCreate(MainActivity.java:22)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.os.Handler.dispatchMessage(Handler.java:99)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.os.Looper.loop(Looper.java:123)
05-10 16:41:13.155: E/AndroidRuntime(9384): at android.app.ActivityThread.main(ActivityThread.java:4627)
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.reflect.Method.invokeNative(Native Method)
05-10 16:41:13.155: E/AndroidRuntime(9384): at java.lang.reflect.Method.invoke(Method.java:521)
05-10 16:41:13.155: E/AndroidRuntime(9384): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
05-10 16:41:13.155: E/AndroidRuntime(9384): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
05-10 16:41:13.155: E/AndroidRuntime(9384): at dalvik.system.NativeStart.main(Native Method)
再想一想,如果那个 for 循环 是 的错误。应该是编译时的问题。为什么它在不同的手机(不同版本的 Android)中表现不同?
得到 an update来自谷歌,他们已经修补了它,并将更正它 in the future release .
与此同时,我已经编写了一个基于their code 的补丁方法。 :
(这是必要的,因为 (1) 我们仍需等待正确的发布,(2) 我们需要处理未进行该固定更新的设备)
/** Patch for the String.replace(CharSequence target, CharSequence replacement),
* because the original is buggy when CharSequence target is empty, i.e. "".
* Patched by Google Android: https://android-review.googlesource.com/58393
*/
public static String replacePatched(final String string, final CharSequence target, final CharSequence replacement) {
if (target == null) {
throw new NullPointerException("target == null");
}
if (replacement == null) {
throw new NullPointerException("replacement == null");
}
final String targetString = target.toString();
int matchStart = string.indexOf(targetString, 0);
if (matchStart == -1) {
// If there's nothing to replace, return the original string untouched.
return new String(string);
}
final char[] value = string.toCharArray(); // required in patch
final int count = value.length; // required in patch
final String replacementString = replacement.toString();
// The empty target matches at the start and end and between each character.
if (targetString.length() == 0) {
// The result contains the original 'count' characters, a copy of the
// replacement string before every one of those characters, and a final
// copy of the replacement string at the end.
final StringBuilder result = new StringBuilder(count + (count + 1) * replacementString.length());
result.append(replacementString);
for (int i = 0; i < count; ++i) {
result.append(value[i]);
result.append(replacementString);
}
return new String(result); // StringBuilder.toString() does not give exact length
}
final StringBuilder result = new StringBuilder(count);
int searchStart = 0;
do {
// Copy characters before the match...
result.append(value, searchStart, matchStart - searchStart);
// Insert the replacement...
result.append(replacementString);
// And skip over the match...
searchStart = matchStart + targetString.length();
} while ((matchStart = string.indexOf(targetString, searchStart)) != -1);
// Copy any trailing chars...
result.append(value, searchStart, count - searchStart);
return new String(result); // StringBuilder.toString() does not give exact length
}
详细版本:
/** Patch for the String.replace(CharSequence target, CharSequence replacement),
* because the original is buggy when CharSequence target is empty, i.e. "".
* Patched by Google Android: https://android-review.googlesource.com/58393
*/
public static String replacePatched(final String string, final CharSequence target, final CharSequence replacement) {
if (target == null) {
throw new NullPointerException("target == null");
}
if (replacement == null) {
throw new NullPointerException("replacement == null");
}
// String targetString = target.toString(); // original
final String targetString = target.toString();
// int matchStart = indexOf(targetString, 0); // original
int matchStart = string.indexOf(targetString, 0);
if (matchStart == -1) {
// If there's nothing to replace, return the original string untouched.
// return this; // original
return new String(string);
}
final char[] value = string.toCharArray(); // required in patch
final int count = value.length; // required in patch
// String replacementString = replacement.toString(); // original
final String replacementString = replacement.toString();
// The empty target matches at the start and end and between each character.
// int targetLength = targetString.length(); // original
// if (targetLength == 0) { // original
if (targetString.length() == 0) {
// int resultLength = (count + 2) * replacementString.length(); // original
// // The result contains the original 'count' characters, a copy of the
// // replacement string before every one of those characters, and a final
// // copy of the replacement string at the end.
// int resultLength = count + (count + 1) * replacementString.length(); // patched by Google Android
// StringBuilder result = new StringBuilder(resultLength); // original
final StringBuilder result = new StringBuilder(count + (count + 1) * replacementString.length());
result.append(replacementString);
// for (int i = offset; i < count; ++i) { // original
// int end = offset + count; // patched by Google Android
// for (int i = offset; i != end; ++i) { // patched by Google Android
for (int i = 0; i < count; ++i) {
result.append(value[i]);
result.append(replacementString);
}
// return result.toString(); // original
return new String(result); // StringBuilder.toString() does not give exact length
}
// StringBuilder result = new StringBuilder(count); // original
final StringBuilder result = new StringBuilder(count);
int searchStart = 0;
do {
// Copy characters before the match...
// result.append(value, offset + searchStart, matchStart - searchStart); // original
result.append(value, searchStart, matchStart - searchStart);
// Insert the replacement...
result.append(replacementString);
// And skip over the match...
// searchStart = matchStart + targetLength; // original
searchStart = matchStart + targetString.length();
// } while ((matchStart = indexOf(targetString, searchStart)) != -1); // original
} while ((matchStart = string.indexOf(targetString, searchStart)) != -1);
// Copy any trailing chars...
// result.append(value, offset + searchStart, count - searchStart); // original
result.append(value, searchStart, count - searchStart);
// return result.toString(); // original
return new String(result); // StringBuilder.toString() does not give exact length
}
关于java - 安卓漏洞? : String. substring(5).replace (“” , “” )//空字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16475317/
所以我实现了ciphersaber-1 .它几乎可以工作,我可以解密 cstest1.cs1。但我无法让 cstest2.cs1 正常工作。 输出是: The Fourth Amendment to
更改 unsat 查询中断言的顺序后,它变为 sat。 查询结构为: definitions1 assertions1 definitions2 bad_assertions check-sat 我使
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我的应用程序用于使用 wifi 进行实时视频流和录制(音频和视频)。使用以下依赖项: repositories { maven { url 'https://raw.github.com/iParse
我正在使用 Delphi,并且我想在我的应用程序中使用 ActiveX 组件(用于压缩)。这会让我的程序更容易受到病毒攻击吗?我的程序是一个备份应用程序,它使用 FTP 和套接字来传输文件和消息。我的
我用这个函数来防止SQL注入(inject) function cleanQuery($string) { if(get_magic_quotes_gpc()) // prevents du
最近我在向我的 friend 解释参数化及其优势,他问我在安全性方面它比 mysqli_escape_string 有什么好处。具体来说,您能想到尽管输入字符串被转义(使用 mysqli_escape
我想我在最新版本的 Highstock 中发现了一个错误: 定义了以下 RangeSelector: rangeSelector: { buttons: [{ typ
我在阅读有关 C 语言字符串中的漏洞的文章后,发现了这段代码。谁能给我解释为什么会这样?提前致谢。 int main (int argc, char* argv[]) { char a[16];
我最近浏览了 php 等的 emacs 模式,并决定选择 nXhtml。但是,我不断收到以下错误:每当我打开一个 html 文件时,整个文件都以蓝色突出显示。不用说,这很烦人。我认为这可能是因为我的
我被分配到我公司的一个遗留 Web 应用程序,在研究源代码一两天后,我发现了一个类似于以下内容的 SQL 注入(inject)向量: mysql_query("SELECT * FROM foo WH
在坚持代码分析错误的过程中,我正在将我的属性更改为具有私有(private) setter 。然后我开始尝试更多地了解为什么。根据一些研究,MS 说 this : A writable collect
我最近开始使用 AngularJS,我想我遇到了一个奇怪的错误。 首先,这是一些工作代码: 查看: Delete Num
阅读时djangobook chapter ,我遇到了提到 csrf 漏洞的部分,其中注销链接被放置在隐藏的恶意站点中。 在我使用 django 创建的 Web 应用程序中,我使用了类似的注销链接 基
以前,在我的应用程序中,我得到了一个 NPE,并且通过在 NullPointerException 处设置断点,可以获得中断、堆栈跟踪(在“调试”窗口中)以及“变量”窗口中的当前变量。 但是,现在其他
我下载了 sponza_obj.rar (sponza.obj + sponza.mtl) 和 sponza_textures.rar Crytek 网站。看起来缺少gi_flag.tga。我在哪里可
在我的应用程序中,我们有许多用户,他们都与不同的调用中心相关。在 URL 中,有一个向后的 hack,他们可以在 ? 后面输入 call_center=number。它将引导他们进入不同的调用中心数据
我正在建立一个带有 SQL 注入(inject)漏洞的网站用于测试目的。但是,我只想配置 SQL 盲注。我有这个 PHP 代码: NEW
我们有一个 ASP.NET/C# 网站。我们的开发人员在亚洲离岸,我刚刚发现他们一直在网站前端放置原始 SQL。 我担心我们现在容易受到 SQL 注入(inject)攻击。有谁知道我如何检测网站上的漏
我正在尝试从代码运行 Microsoft Rdp 应用程序。 我有以下伪代码,SonarQube 提示命令注入(inject)漏洞 String rdpFilePath = myObject.getR
我是一名优秀的程序员,十分优秀!