Skip to content

Commit

Permalink
Bugfix for empty string in const pool
Browse files Browse the repository at this point in the history
  • Loading branch information
hextriclosan committed Oct 28, 2024
1 parent 3e74f29 commit 240d321
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
12 changes: 12 additions & 0 deletions tests/empty_string_in_cpool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod utils;
use utils::get_int;
use utils::setup;

#[test]
fn empty_string_in_cpool() {
let mut vm = setup();
let last_frame_value = vm
.run("samples.javacore.strings.trivial.EmptyStringInCPool")
.unwrap();
assert_eq!(0, get_int(last_frame_value))
}
7 changes: 7 additions & 0 deletions tests/test_data/EmptyStringInCPool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package samples.javacore.strings.trivial;

public class EmptyStringInCPool {
public static void main(String[] args) {
int result = "".length();
}
}
Binary file not shown.
35 changes: 35 additions & 0 deletions vm/src/execution_engine/string_pool_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ impl StringPoolHelper {
}

fn create_string(string: &str) -> crate::error::Result<i32> {
if string.is_empty() {
return Self::create_empty_string();
}

let codepoints = Self::string_to_codepoints(&string);

let array_ref =
Expand Down Expand Up @@ -50,6 +54,37 @@ impl StringPoolHelper {
Ok(string_instance_ref)
}

// todo: consider creating all CPool strings like this
fn create_empty_string() -> crate::error::Result<i32> {
let byte_array_ref =
with_heap_write_lock(|heap| heap.create_array_with_values("[b", &vec![]));
let string_class_name = "java/lang/String".to_string();
let instance_with_default_fields = with_method_area(|method_area| {
method_area.create_instance_with_default_fields(&string_class_name)
});

let string_instance_ref =
with_heap_write_lock(|heap| heap.create_instance(instance_with_default_fields));

let full_signature = "<init>:([BB)V";
let rc = with_method_area(|method_area| method_area.get(string_class_name.as_str()))?;
let special_method = rc
.methods
.method_by_signature
.get(full_signature)
.ok_or_else(|| Error::new_constant_pool(&format!("Error getting JavaMethod by class name {string_class_name} and full signature {full_signature} invoking special")))?;

let mut engine = Engine::new();
let mut stack_frame = special_method.new_stack_frame()?;
stack_frame.set_local(0, string_instance_ref);
stack_frame.set_local(1, byte_array_ref);
stack_frame.set_local(2, 0); // coder LATIN1

engine.execute(stack_frame)?;

Ok(string_instance_ref)
}

fn string_to_codepoints(s: &str) -> Vec<i32> {
s.chars().map(|c| c as i32).collect()
}
Expand Down

0 comments on commit 240d321

Please sign in to comment.