summaryrefslogtreecommitdiff
path: root/debian/patches/jdk-freetypeScaler-crash.diff
blob: 4d68018a7113a2e90ac0690cdbc104d4d94d7744 (plain)
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);