1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
Description:
Fixing the bad JNI code in the font manager code. Two issues:
o The JNIEnv is unique to the thread. It cannot be saved by one thread and
reused by another. Use GetEnv instead.
o The 'font2D' jobject needs to be converted into a global reference because
its lifetime exceeds the lifetime of a native method call.
Evaluation:
Appropriately register/free everything with the garbage collector.
Fix:
# HG changeset patch
# User martin
# Date 1224202830 25200
# Node ID 3c9d6001d8a90698a3540a2a483717f26a98db78
# Parent 68730f05449cd4f39ce1cb82adc6c4e57f87554f
Crash in freetypeScaler.c due to insufficient GC protection
Summary: NewGlobalRef/DeleteGlobalRef as needed.
Reviewed-by:
Contributed-by: yamauchi@google.com
--- a/jdk/make/mapfiles/libfontmanager/mapfile-vers.openjdk
+++ b/jdk/make/mapfiles/libfontmanager/mapfile-vers.openjdk
@@ -29,6 +29,7 @@
SUNWprivate_1.1 {
global:
+ JNI_OnLoad;
getSunFontIDs;
newLayoutTableCache;
freeLayoutTableCache;
--- a/jdk/src/share/native/sun/font/freetypeScaler.c
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c
@@ -48,16 +48,6 @@
#define ROUND(x) ((int) (x+0.5))
typedef struct {
- /* Important note:
- JNI forbids sharing same env between different threads.
- We are safe, because pointer is overwritten every time we get into
- JNI call (see setupFTContext).
-
- Pointer is used by font data reading callbacks
- such as ReadTTFontFileFunc.
-
- NB: We may consider switching to JNI_GetEnv. */
- JNIEnv* env;
FT_Library library;
FT_Face face;
jobject font2D;
@@ -90,6 +80,13 @@ int z_verbose;
void z_error(char *s) {}
#endif
+static JavaVM* jvm = NULL;
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+ jvm = vm;
+ return JNI_VERSION_1_2;
+}
+
/**************** Error handling utilities *****************/
static jmethodID invalidateScalerMID;
@@ -120,6 +117,10 @@ static void freeNativeResources(JNIEnv *
FT_Done_Face(scalerInfo->face);
FT_Done_FreeType(scalerInfo->library);
+ if (scalerInfo->font2D != NULL) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
+ }
+
if (scalerInfo->directBuffer != NULL) {
(*env)->DeleteGlobalRef(env, scalerInfo->directBuffer);
}
@@ -152,8 +153,8 @@ static unsigned long ReadTTFontFileFunc(
unsigned char* destBuffer,
unsigned long numBytes)
{
+ JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
FTScalerInfo *scalerInfo = (FTScalerInfo *) stream->pathname.pointer;
- JNIEnv* env = scalerInfo->env;
jobject bBuffer;
int bread = 0;
@@ -229,8 +230,7 @@ Java_sun_font_FreetypeFontScaler_initNat
if (scalerInfo == NULL)
return 0;
- scalerInfo->env = env;
- scalerInfo->font2D = font2D;
+ scalerInfo->font2D = (*env)->NewGlobalRef(env, font2D);
scalerInfo->fontDataOffset = 0;
scalerInfo->fontDataLength = 0;
scalerInfo->fileSize = filesize;
@@ -247,6 +247,7 @@ Java_sun_font_FreetypeFontScaler_initNat
*/
error = FT_Init_FreeType(&scalerInfo->library);
if (error) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
free(scalerInfo);
return 0;
}
@@ -317,6 +318,7 @@ Java_sun_font_FreetypeFontScaler_initNat
}
if (scalerInfo->fontData != NULL)
free(scalerInfo->fontData);
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
free(scalerInfo);
return 0;
}
@@ -377,8 +379,10 @@ static int setupFTContext(JNIEnv *env,
FTScalerContext *context) {
int errCode = 0;
- scalerInfo->env = env;
- scalerInfo->font2D = font2D;
+ if (scalerInfo->font2D != NULL) {
+ (*env)->DeleteGlobalRef(env, scalerInfo->font2D);
+ }
+ scalerInfo->font2D = (*env)->NewGlobalRef(env, font2D);
if (context != NULL) {
FT_Set_Transform(scalerInfo->face, &context->transform, NULL);
|