Skip to content

Commit a4fba82

Browse files
gilles-duboscqrakachan
authored andcommitted
[GR-68388] Espresso: misc. fixes.
PullRequest: graal/21727
2 parents 6cdaf2c + 2ddf52d commit a4fba82

File tree

5 files changed

+123
-30
lines changed
  • espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors
  • espresso/src

5 files changed

+123
-30
lines changed

espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/descriptors/ModifiedUTF8.java

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* Spec - The CONSTANT_Utf8_info Structure</a>
4141
*/
4242
public sealed class ModifiedUTF8 permits Descriptor, Name {
43+
private static final char REPLACEMENT_CHARACTER = 0xfffd;
4344

4445
/**
4546
* Type-safe cast from Symbol with ModifiedUTF8 bound to Symbol<ModifiedUTF8>.
@@ -146,6 +147,12 @@ public static String toJavaString(byte[] bytearr, int offset, int utflen) throws
146147
return toJavaString(ByteBuffer.wrap(bytearr, offset, utflen));
147148
}
148149

150+
/**
151+
* Creates a String from the contents of the buffer, interpreted as modified utf8. if the
152+
* contents is not valid modified utf8, {@link UTFDataFormatException} will be thrown.
153+
*
154+
* @throws UTFDataFormatException if the data is not valid modified utf8.
155+
*/
149156
public static String toJavaString(ByteBuffer buffer) throws IOException {
150157
char[] chararr = new char[buffer.remaining()];
151158

@@ -209,7 +216,87 @@ public static String toJavaString(ByteBuffer buffer) throws IOException {
209216
throw throwUTFDataFormatException(malformedInputMessage(buffer.position()));
210217
}
211218
}
212-
// The number of chars produced may be less than utflen
219+
// The number of chars produced may be less than the size of the buffer
220+
return new String(chararr, 0, chararrCount);
221+
}
222+
223+
/**
224+
* Creates a String from the contents of the buffer, interpreted as modified utf8. If some bytes
225+
* cannot be decoded, the Unicode replacement character (0xfffd) is used.
226+
*/
227+
public static String toJavaStringSafe(ByteBuffer buffer) {
228+
char[] chararr = new char[buffer.remaining()];
229+
230+
int c;
231+
int char2;
232+
int char3;
233+
int chararrCount = 0;
234+
235+
while (buffer.hasRemaining()) {
236+
c = buffer.get() & 0xff;
237+
if (c > 127) {
238+
buffer.position(buffer.position() - 1);
239+
break;
240+
}
241+
chararr[chararrCount++] = (char) c;
242+
}
243+
244+
while (buffer.hasRemaining()) {
245+
c = buffer.get() & 0xff;
246+
switch (c >> 4) {
247+
case 0:
248+
case 1:
249+
case 2:
250+
case 3:
251+
case 4:
252+
case 5:
253+
case 6:
254+
case 7:
255+
/* 0xxxxxxx */
256+
chararr[chararrCount++] = (char) c;
257+
break;
258+
case 12:
259+
case 13:
260+
/* 110x xxxx 10xx xxxx */
261+
if (!buffer.hasRemaining()) {
262+
if (chararrCount < chararr.length) {
263+
chararr[chararrCount] = REPLACEMENT_CHARACTER;
264+
break;
265+
}
266+
}
267+
char2 = buffer.get();
268+
if ((char2 & 0xC0) != 0x80) {
269+
chararr[chararrCount++] = REPLACEMENT_CHARACTER;
270+
break;
271+
}
272+
chararr[chararrCount++] = (char) (((c & 0x1F) << 6) |
273+
(char2 & 0x3F));
274+
break;
275+
case 14:
276+
/* 1110 xxxx 10xx xxxx 10xx xxxx */
277+
if (buffer.remaining() < 2) {
278+
if (chararrCount < chararr.length) {
279+
chararr[chararrCount] = REPLACEMENT_CHARACTER;
280+
break;
281+
}
282+
}
283+
char2 = buffer.get();
284+
char3 = buffer.get();
285+
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
286+
chararr[chararrCount++] = REPLACEMENT_CHARACTER;
287+
break;
288+
}
289+
chararr[chararrCount++] = (char) (((c & 0x0F) << 12) |
290+
((char2 & 0x3F) << 6) |
291+
((char3 & 0x3F) << 0));
292+
break;
293+
default:
294+
/* 10xx xxxx, 1111 xxxx */
295+
chararr[chararrCount++] = REPLACEMENT_CHARACTER;
296+
break;
297+
}
298+
}
299+
// The number of chars produced may be less than the size of the buffer
213300
return new String(chararr, 0, chararrCount);
214301
}
215302

espresso/src/com.oracle.truffle.espresso.libjavavm/src/com/oracle/truffle/espresso/libjavavm/LibEspresso.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ static int createJavaVM(@SuppressWarnings("unused") IsolateThread thread, JNIJav
111111
context.close(true);
112112
}
113113
return JNIErrors.JNI_ERR();
114+
} catch (IllegalArgumentException e) {
115+
// This can happen during option processing (build call above)
116+
// OptionType converters can throw IllegalArgumentException
117+
STDERR.println(e.getMessage());
118+
return JNIErrors.JNI_ERR();
114119
}
115120
Value java = bindings.getMember("<JavaVM>");
116121
if (!java.isNativePointer()) {
@@ -161,7 +166,12 @@ static int enterContext(@SuppressWarnings("unused") IsolateThread thread, JNIJav
161166
STDERR.println("Cannot enter context: no context found");
162167
return JNIErrors.JNI_ERR();
163168
}
164-
context.enter();
169+
try {
170+
context.enter();
171+
} catch (PolyglotException | IllegalStateException e) {
172+
STDERR.println("Cannot enter context: " + e.getMessage());
173+
return JNIErrors.JNI_ERR();
174+
}
165175
return JNIErrors.JNI_OK();
166176
}
167177

@@ -173,7 +183,12 @@ static int leaveContext(@SuppressWarnings("unused") IsolateThread thread, JNIJav
173183
STDERR.println("Cannot leave context: no context found");
174184
return JNIErrors.JNI_ERR();
175185
}
176-
context.leave();
186+
try {
187+
context.leave();
188+
} catch (IllegalStateException e) {
189+
STDERR.println("Cannot leave context: " + e.getMessage());
190+
return JNIErrors.JNI_ERR();
191+
}
177192
return JNIErrors.JNI_OK();
178193
}
179194

@@ -189,8 +204,13 @@ static int closeContext(@SuppressWarnings("unused") IsolateThread thread, JNIJav
189204
ObjectHandle contextHandle = javaVM.getFunctions().getContext();
190205
Context context = ObjectHandles.getGlobal().get(contextHandle);
191206
ObjectHandles.getGlobal().destroy(contextHandle);
192-
context.leave();
193-
context.close();
207+
try {
208+
context.leave();
209+
context.close();
210+
} catch (PolyglotException | IllegalStateException e) {
211+
STDERR.println("Cannot close context: " + e.getMessage());
212+
return JNIErrors.JNI_ERR();
213+
}
194214
return JNIErrors.JNI_OK();
195215
}
196216

espresso/src/com.oracle.truffle.espresso.mokapot/src/mokapot.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,7 @@ JNIEXPORT jboolean JNICALL JVM_IsForeignLinkerSupported(void) {
17281728

17291729
JNIEXPORT jboolean JNICALL
17301730
JVM_IsStaticallyLinked(void) {
1731-
UNIMPLEMENTED(JVM_IsStaticallyLinked);
1731+
IMPLEMENTED(JVM_IsStaticallyLinked);
17321732
return JNI_FALSE;
17331733
}
17341734

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ffi/nfi/NativeUtils.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
*/
2323
package com.oracle.truffle.espresso.ffi.nfi;
2424

25-
import java.io.IOException;
2625
import java.nio.ByteBuffer;
2726
import java.nio.ByteOrder;
2827
import java.nio.IntBuffer;
@@ -172,21 +171,12 @@ public static String fromUTF8Ptr(long rawBytesPtr) {
172171
return null;
173172
}
174173
ByteBuffer buf = directByteBuffer(rawBytesPtr, Integer.MAX_VALUE);
175-
176-
int utfLen = 0;
177174
while (buf.get() != 0) {
178-
utfLen++;
179-
}
180-
181-
byte[] bytes = new byte[utfLen];
182-
buf.clear();
183-
buf.get(bytes);
184-
try {
185-
return ModifiedUTF8.toJavaString(bytes);
186-
} catch (IOException e) {
187-
// return StaticObject.NULL;
188-
throw EspressoError.shouldNotReachHere(e);
175+
// find the end of the utf8
189176
}
177+
buf.limit(buf.position() - 1);
178+
buf.position(0);
179+
return ModifiedUTF8.toJavaStringSafe(buf);
190180
}
191181

192182
@TruffleBoundary

espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/JavaAgents.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,13 @@ private JavaAgent[] initializeAgents(List<String> agentOptions) {
103103

104104
private void onLoad(String javaAgentName, String agentOptions, List<JavaAgent> addedAgents) {
105105
Path jarPath = Paths.get(javaAgentName);
106-
if (jarPath.isAbsolute()) {
107-
try {
108-
JavaAgent javaAgent = addAgent(jarPath, agentOptions);
109-
if (javaAgent != null) {
110-
addedAgents.add(javaAgent);
111-
}
112-
} catch (IOException e) {
113-
throw getContext().abort("Error opening zip file or JAR manifest missing : " + jarPath + " due to: " + e.getMessage());
106+
try {
107+
JavaAgent javaAgent = addAgent(jarPath, agentOptions);
108+
if (javaAgent != null) {
109+
addedAgents.add(javaAgent);
114110
}
115-
} else {
116-
throw getContext().abort("Please use an absolute path for java agent: " + jarPath);
111+
} catch (IOException e) {
112+
throw getContext().abort("Error opening zip file or JAR manifest missing : " + jarPath + " due to: " + e.getMessage());
117113
}
118114
}
119115

0 commit comments

Comments
 (0)