Package: libopengl-perl / 0.7000+dfsg-3

pointer-truncation-glutTimerFunc.patch Patch series | download
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
Description: Fix https://bugs.debian.org/886496
   * Patched pogl_glut.xs to fix pointer truncation in glutTimerFunc
     (Closes: #886496)
Author: Thomas Kremer <bugs.debian@xorg.c-informatik.de>
Bug-Debian: https://bugs.debian.org/886496
Last-Update: 2019-01-23

--- a/pogl_glut.xs
+++ b/pogl_glut.xs
@@ -441,10 +441,27 @@
 	DO_perl_call_sv(handler, G_DISCARD);
 }
 
+/* glut_timer_handlers is an allocation buffer.
+   All unused elements are SVivs forming a linked-list,
+   starting at glut_timer_handlers_next_free.
+   The end of the list is marked by a -1.
+   If no element is free when one is needed, the buffer will grow.
+*/
+static AV * glut_timer_handlers = 0;
+static int glut_timer_handlers_next_free = -1;
+
 /* Callback for glutTimerFunc */
 static void generic_glut_timer_handler(int value)
 {
-	AV * handler_data = (AV*)value;
+	if (!glut_timer_handlers)
+		croak("Timer handler called, but no timers have ever been set up");
+	SV** h = av_fetch(glut_timer_handlers,value,FALSE);
+	if (!h || !SvOK(*h) || !SvROK(*h))
+		croak("Timer handler called for unregistered timer");
+	AV * handler_data = (AV*)SvRV(*h);
+	sv_setiv(*h,glut_timer_handlers_next_free);
+	glut_timer_handlers_next_free = value;
+
 	SV * handler;
 	int i;
 	dSP;
@@ -1017,8 +1034,24 @@
 			AV * handler_data = newAV();
 		
 			PackCallbackST(handler_data, 1);
+			SV * handler_data_sv = newRV_inc((SV*)handler_data);
 			
-			glutTimerFunc(msecs, generic_glut_timer_handler, (int)handler_data);
+			if (!glut_timer_handlers)
+				glut_timer_handlers = newAV();
+
+			int handler_id = glut_timer_handlers_next_free;
+			if (handler_id == -1) {
+			  handler_id = ((int) av_top_index(glut_timer_handlers))+1;
+			  if (handler_id < 0)
+			    croak("Limit of concurrent timers reached (MAX_INT)");
+			  av_push(glut_timer_handlers, handler_data_sv);
+			} else {
+			  SV** entry = av_fetch(glut_timer_handlers,handler_id,FALSE);
+			  glut_timer_handlers_next_free = SvIV(*entry);
+			  sv_setsv(*entry,sv_2mortal(handler_data_sv));
+			}
+
+			glutTimerFunc(msecs, generic_glut_timer_handler, handler_id);
 		}
 	ENSURE_callback_thread;}