55#include "perl.h"
66#include "XSUB.h"
77#include "ppport.h"
8+ #include <time.h>
9+ #include <stdlib.h>
810
911#define NEED_newRV_noinc
1012#define DUKTAPE_DONT_LOAD_SHARED
1113
14+
1215#include "./lib/duktape.c"
1316#include "./lib/module-duktape/duk_module_duktape.c"
1417#include "./lib/print-alert/duk_print_alert.c"
2023
2124
2225
26+ typedef struct {
27+ /* The double value in the union is there to ensure alignment is
28+ * good for IEEE doubles too. In many 32-bit environments 4 bytes
29+ * would be sufficiently aligned and the double value is unnecessary.
30+ */
31+ union {
32+ size_t sz ;
33+ double d ;
34+ } u ;
35+ } perlDukMemHdr ;
36+
37+ typedef struct {
38+ int timeout ;
39+ size_t max_memory ;
40+ size_t total_allocated ;
41+ duk_context * ctx ;
42+ } perlDuk ;
43+
44+
45+
2346/**
24- * dump_stack
25- * for debugging
47+ * perl_duk_exec_timeout
2648******************************************************************************/
27- int dump_stack (duk_context * ctx , const char * name ) {
28- duk_idx_t i , n ;
29- n = duk_get_top (ctx );
30- printf ("%s (top=%ld):" , name , (long ) n );
31- for (i = 0 ; i < n ; i ++ ) {
32- printf (" " );
33- duk_dup (ctx , i );
34- printf ("%s" , duk_safe_to_string (ctx , -1 ));
35- duk_pop (ctx );
49+ int perl_duk_exec_timeout ( void * udata ) {
50+ perlDuk * duk = (perlDuk * ) udata ;
51+ int timeout = duk -> timeout ;
52+
53+ if (timeout > 0 ){
54+ clock_t uptime = clock ();
55+ int passed_time = (int )(uptime / CLOCKS_PER_SEC );
56+ if (passed_time > timeout ){
57+ return 1 ;
58+ }
3659 }
37- printf ("\n" );
38- fflush (stdout );
39- return 1 ;
60+ return 0 ;
61+ }
62+
63+
64+
65+ /**
66+ * duk_sandbox_alloc
67+ ******************************************************************************/
68+ static void * duk_sandbox_alloc (void * udata , duk_size_t size ) {
69+ perlDuk * duk = (perlDuk * ) udata ;
70+ perlDukMemHdr * hdr ;
71+
72+ size_t max_memory = duk -> max_memory ;
73+ size_t total_allocated = duk -> total_allocated ;
74+
75+ if (size == 0 ) return NULL ;
76+
77+ if (total_allocated + size >= max_memory ) {
78+ duk -> total_allocated = 0 ;
79+ return NULL ;
80+ }
81+
82+ hdr = (perlDukMemHdr * ) malloc (size + sizeof (perlDukMemHdr ));
83+ if (!hdr ) return NULL ;
84+
85+ hdr -> u .sz = size ;
86+ duk -> total_allocated += size ;
87+ return (void * ) (hdr + 1 );
88+ }
89+
90+
91+
92+ /**
93+ * duk_sandbox_realloc
94+ ******************************************************************************/
95+ static void * duk_sandbox_realloc (void * udata , void * ptr , duk_size_t size ) {
96+ perlDukMemHdr * hdr ;
97+ size_t old_size ;
98+ void * t ;
99+
100+ perlDuk * duk = (perlDuk * ) udata ;
101+ size_t max_memory = duk -> max_memory ;
102+ size_t total_allocated = duk -> total_allocated ;
103+
104+ if (ptr ) {
105+ hdr = (perlDukMemHdr * ) (((char * ) ptr ) - sizeof (perlDukMemHdr ));
106+ old_size = hdr -> u .sz ;
107+
108+ if (size == 0 ) {
109+ duk -> total_allocated -= old_size ;
110+ free ((void * ) hdr );
111+ return NULL ;
112+ }
113+
114+ if (total_allocated - old_size + size > max_memory ) {
115+ duk -> total_allocated = 0 ;
116+ return NULL ;
117+ }
118+
119+ t = realloc ((void * ) hdr , size + sizeof (perlDukMemHdr ));
120+ if (!t ) return NULL ;
121+
122+ hdr = (perlDukMemHdr * ) t ;
123+ duk -> total_allocated -= old_size ;
124+ duk -> total_allocated += size ;
125+ hdr -> u .sz = size ;
126+ return (void * ) (hdr + 1 );
127+ } else {
128+ if (size == 0 ) return NULL ;
129+
130+ if (total_allocated + size > max_memory ) {
131+ duk -> total_allocated = 0 ;
132+ return NULL ;
133+ }
134+
135+ hdr = (perlDukMemHdr * ) malloc (size + sizeof (perlDukMemHdr ));
136+ if (!hdr ) return NULL ;
137+
138+ hdr -> u .sz = size ;
139+ duk -> total_allocated += size ;
140+ return (void * ) (hdr + 1 );
141+ }
142+ }
143+
144+
145+
146+ /**
147+ * duk_sandbox_free
148+ ******************************************************************************/
149+ static void duk_sandbox_free (void * udata , void * ptr ) {
150+ perlDukMemHdr * hdr ;
151+
152+ perlDuk * duk = (perlDuk * ) udata ;
153+
154+ if (!ptr ) return ;
155+
156+ hdr = (perlDukMemHdr * ) (((char * ) ptr ) - sizeof (perlDukMemHdr ));
157+ duk -> total_allocated -= hdr -> u .sz ;
158+ free ((void * ) hdr );
159+ }
160+
161+
162+
163+ /**
164+ * get_user_data
165+ ******************************************************************************/
166+ perlDuk * get_user_data (duk_context * ctx ){
167+ duk_memory_functions funcs ;
168+ duk_get_memory_functions (ctx , & funcs );
169+ return (perlDuk * )funcs .udata ;
40170}
41171
42172
@@ -53,12 +183,23 @@ void fatal_handler (void *udata, const char *msg) {
53183/**
54184 * new
55185******************************************************************************/
56- SV * perl_duk_new (const char * classname ) {
186+ SV * perl_duk_new (const char * classname , size_t max_memory ) {
57187 duk_context * ctx ;
58- SV * obj ;
59- SV * obj_ref ;
188+ SV * obj ;
189+ SV * obj_ref ;
190+
191+ perlDuk * duk = malloc (sizeof (* duk ));
192+ duk -> ctx = NULL ;
193+ duk -> timeout = 0 ;
194+ duk -> max_memory = max_memory ;
195+ duk -> total_allocated = 0 ;
196+
197+ if (max_memory > 0 ){
198+ ctx = duk_create_heap (duk_sandbox_alloc , duk_sandbox_realloc , duk_sandbox_free , (void * )duk , fatal_handler );
199+ } else {
200+ ctx = duk_create_heap (NULL , NULL , NULL , (void * )duk , fatal_handler );
201+ }
60202
61- ctx = duk_create_heap (NULL , NULL , NULL , NULL , fatal_handler );
62203 duk_module_duktape_init (ctx );
63204 duk_print_alert_init (ctx , 0 );
64205
@@ -67,11 +208,38 @@ SV *perl_duk_new(const char * classname) {
67208 sv_bless (obj_ref , gv_stashpv (classname , GV_ADD ));
68209 SvREADONLY_on (obj );
69210
211+ duk -> ctx = ctx ;
70212 return obj_ref ;
71213}
72214
73215
74216
217+ /**
218+ * perl_duk_set_timeout
219+ ******************************************************************************/
220+ void perl_duk_set_timeout (duk_context * ctx , int timeout ){
221+ perlDuk * duk = get_user_data (ctx );
222+ int current = 0 ;
223+
224+ if (timeout > 0 ){
225+ timeout += (int )(clock () / CLOCKS_PER_SEC );
226+ }
227+
228+ duk -> timeout = current + timeout ;
229+ }
230+
231+
232+
233+ /**
234+ * perl_duk_resize_memory
235+ ******************************************************************************/
236+ void perl_duk_resize_memory (duk_context * ctx , size_t max_memory ){
237+ perlDuk * duk = get_user_data (ctx );
238+ duk -> max_memory = max_memory ;
239+ }
240+
241+
242+
75243/**
76244 * perl_duk_reset_top
77245 * quick helper function to reset stack top
@@ -81,16 +249,18 @@ void perl_duk_reset_top(duk_context *ctx){
81249 duk_pop_n (ctx , top );
82250}
83251
252+
253+
84254/**
85255 * is number
86256******************************************************************************/
87257int duk_sv_is_number (SV * sv ) {
88- if (SvIOK (sv ) || SvNOK (sv )){
89- return 1 ;
90- }
258+ if (SvIOK (sv ) || SvNOK (sv )) return 1 ;
91259 return 0 ;
92260}
93261
262+
263+
94264/**
95265 * call_safe_perl_sub
96266******************************************************************************/
@@ -273,11 +443,25 @@ int duktape_dlClose(duk_context *ctx, void *dlHandle){
273443}
274444
275445
446+
447+ /**
448+ * destructions
449+ ******************************************************************************/
450+ void free_perl_duk (duk_context * ctx ){
451+ perlDuk * duk = get_user_data (ctx );
452+ if (duk != NULL ) free (duk );
453+ }
454+
455+
456+ // not callabel
276457void DESTROY (duk_context * ctx ) {
458+ perlDuk * duk = get_user_data (ctx );
459+ if (duk != NULL ) free (duk );
277460 printf ("Destroying %p\n" , ctx );
278- //Safefree(ctx);
279461}
280462
463+
464+
281465/*
282466 Auto Generated C Code by parser.pl
283467 parser.pl reads duktape.h file and create both
0 commit comments