iodine 0.7.33 → 0.7.34

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 430ea5b683f9561e44a9e1b4f6ab56f1b9c6e58637b3ecaae9f414eed58cc1ba
4
- data.tar.gz: 17a876d312611ccb0892a9f41b6ae6ca9fa0257b8c78778a7a8edf545f3dc165
3
+ metadata.gz: 37df76fb8d575cf00bba0d36342aa6eabd5fba95a4d2940b61ce9b3026082dc1
4
+ data.tar.gz: 0a5f7fe186c7c824d15959cbabaa71edaffc8159780a7054a54bf959f36b465a
5
5
  SHA512:
6
- metadata.gz: 3db4b691bae4fe0745c36b4d29a960bfd712e7cb3a29cc9f4e2f357a680f3c325b808bff8720a9f3835d8b0c86c725a0542c0d1800e2c38fd77198ee8f13399d
7
- data.tar.gz: 0404f0211d42ece456f46bfa89b945f3c01d1b87770c612e276743aa3a82519b40e6705854f66a5bceb9d9e3fea27fe86ad9081d3a86271e5cccd07f6c6f0df8
6
+ metadata.gz: 304dda003c1272727bc279126cc008c27cff83233080ede66817dcb1a3849e149f4b64765642705020013e8d7817726dcbb7039eff8809cf63229cff861a3be7
7
+ data.tar.gz: 27cdeee27782a72ea42c931fb43f09660a8627fdb26c9afb4ce084047b0a10b4e8648adb660f796c1ac12db05fdf011306e2b0dfeaae57212b0f45a21503e39c
@@ -6,6 +6,10 @@ Please notice that this change log contains changes for upcoming releases as wel
6
6
 
7
7
  ## Changes:
8
8
 
9
+ #### Change log v.0.7.34
10
+
11
+ **Security**: (`facil.io`, `http`) updated to facil.io 0.7.3, incorporating it's bug fixes and security updates.
12
+
9
13
  #### Change log v.0.7.33
10
14
 
11
15
  **Fix**: (`iodine`) exception protection would fail and crash if the exception throws wasn't of type `Exception`. I'm not sure how this would happen, but on some Ruby versions it appeared to have occur, maybe where a custom `raise` would be called with a non-exception type. The issue was fixed by testing for the availability of the `message` and `backtrace` functions. Credit to Jan Biedermann (@janbiedermann) for exposing this issue (#76).
@@ -1178,12 +1178,13 @@ static inline void fio_mark_time(void) {
1178
1178
  /** Calculates the due time for a task, given it's interval */
1179
1179
  static struct timespec fio_timer_calc_due(size_t interval) {
1180
1180
  struct timespec now = fio_last_tick();
1181
- if (interval > 1000) {
1182
- now.tv_sec += interval / 1000;
1183
- interval -= interval / 1000;
1181
+ if (interval >= 1000) {
1182
+ unsigned long long secs = interval / 1000;
1183
+ now.tv_sec += secs;
1184
+ interval -= secs * 1000;
1184
1185
  }
1185
1186
  now.tv_nsec += (interval * 1000000UL);
1186
- if (now.tv_nsec > 1000000000L) {
1187
+ if (now.tv_nsec >= 1000000000L) {
1187
1188
  now.tv_nsec -= 1000000000L;
1188
1189
  now.tv_sec += 1;
1189
1190
  }
@@ -1346,7 +1347,7 @@ Section Start Marker
1346
1347
  ***************************************************************************** */
1347
1348
 
1348
1349
  volatile uint8_t fio_signal_children_flag = 0;
1349
-
1350
+ volatile fio_lock_i fio_signal_set_flag = 0;
1350
1351
  /* store old signal handlers to propegate signal handling */
1351
1352
  static struct sigaction fio_old_sig_chld;
1352
1353
  static struct sigaction fio_old_sig_pipe;
@@ -1415,7 +1416,7 @@ static void sig_int_handler(int sig) {
1415
1416
  break;
1416
1417
  }
1417
1418
  /* propagate signale handling to previous existing handler (if any) */
1418
- if (old->sa_handler != SIG_IGN && old->sa_handler != SIG_DFL)
1419
+ if (old && old->sa_handler != SIG_IGN && old->sa_handler != SIG_DFL)
1419
1420
  old->sa_handler(sig);
1420
1421
  }
1421
1422
 
@@ -1423,7 +1424,7 @@ static void sig_int_handler(int sig) {
1423
1424
  static void fio_signal_handler_setup(void) {
1424
1425
  /* setup signal handling */
1425
1426
  struct sigaction act;
1426
- if (fio_old_sig_int.sa_handler)
1427
+ if (fio_trylock(&fio_signal_set_flag))
1427
1428
  return;
1428
1429
 
1429
1430
  memset(&act, 0, sizeof(act));
@@ -1457,8 +1458,9 @@ static void fio_signal_handler_setup(void) {
1457
1458
 
1458
1459
  void fio_signal_handler_reset(void) {
1459
1460
  struct sigaction old;
1460
- if (!fio_old_sig_int.sa_handler)
1461
+ if (fio_signal_set_flag)
1461
1462
  return;
1463
+ fio_unlock(&fio_signal_set_flag);
1462
1464
  memset(&old, 0, sizeof(old));
1463
1465
  sigaction(SIGINT, &fio_old_sig_int, &old);
1464
1466
  sigaction(SIGTERM, &fio_old_sig_term, &old);
@@ -2968,7 +2970,7 @@ ssize_t fio_flush(intptr_t uuid) {
2968
2970
  goto test_errno;
2969
2971
  }
2970
2972
 
2971
- if (uuid_data(uuid).packet_count >= 1024 &&
2973
+ if (uuid_data(uuid).packet_count >= FIO_SLOWLORIS_LIMIT &&
2972
2974
  uuid_data(uuid).packet == old_packet &&
2973
2975
  uuid_data(uuid).sent >= old_sent &&
2974
2976
  (uuid_data(uuid).sent - old_sent) < 32768) {
@@ -3533,11 +3535,12 @@ static void __attribute__((destructor)) fio_lib_destroy(void) {
3533
3535
  fio_data->active = 0;
3534
3536
  fio_on_fork();
3535
3537
  fio_defer_perform();
3538
+ fio_timer_clear_all();
3539
+ fio_defer_perform();
3536
3540
  fio_state_callback_force(FIO_CALL_AT_EXIT);
3537
3541
  fio_state_callback_clear_all();
3538
3542
  fio_defer_perform();
3539
3543
  fio_poll_close();
3540
- fio_timer_clear_all();
3541
3544
  fio_free(fio_data);
3542
3545
  /* memory library destruction must be last */
3543
3546
  fio_mem_destroy();
@@ -3811,15 +3814,16 @@ static void fio_worker_cleanup(void) {
3811
3814
  fio_force_close(fd2uuid(i));
3812
3815
  }
3813
3816
  }
3814
- fio_defer_perform();
3815
- fio_state_callback_force(FIO_CALL_ON_FINISH);
3817
+ fio_timer_clear_all();
3816
3818
  fio_defer_perform();
3817
3819
  if (!fio_data->is_worker) {
3818
- fio_cluster_signal_children();
3820
+ kill(0, SIGINT);
3819
3821
  while (wait(NULL) != -1)
3820
3822
  ;
3821
3823
  }
3822
3824
  fio_defer_perform();
3825
+ fio_state_callback_force(FIO_CALL_ON_FINISH);
3826
+ fio_defer_perform();
3823
3827
  fio_signal_handler_reset();
3824
3828
  if (fio_data->parent == getpid()) {
3825
3829
  FIO_LOG_INFO(" --- Shutdown Complete ---\n");
@@ -5125,7 +5129,7 @@ struct subscription_s {
5125
5129
  void *udata1;
5126
5130
  void *udata2;
5127
5131
  /** reference counter. */
5128
- uintptr_t ref;
5132
+ volatile uintptr_t ref;
5129
5133
  /** prevents the callback from running concurrently for multiple messages. */
5130
5134
  fio_lock_i lock;
5131
5135
  fio_lock_i unsubscribed;
@@ -6202,7 +6206,7 @@ static void fio_cluster_listen_on_close(intptr_t uuid,
6202
6206
  (int)getpid());
6203
6207
  #endif
6204
6208
  if (fio_data->active)
6205
- fio_stop();
6209
+ kill(0, SIGINT);
6206
6210
  }
6207
6211
  (void)uuid;
6208
6212
  }
@@ -6244,6 +6248,7 @@ static void fio_cluster_client_handler(struct cluster_pr_s *pr) {
6244
6248
  break;
6245
6249
  case FIO_CLUSTER_MSG_SHUTDOWN:
6246
6250
  fio_stop();
6251
+ kill(getpid(), SIGINT);
6247
6252
  case FIO_CLUSTER_MSG_ERROR: /* fallthrough */
6248
6253
  case FIO_CLUSTER_MSG_PING: /* fallthrough */
6249
6254
  case FIO_CLUSTER_MSG_ROOT: /* fallthrough */
@@ -6498,7 +6503,7 @@ static void fio_pubsub_on_fork(void) {
6498
6503
  /** Signals children (or self) to shutdown) - NOT signal safe. */
6499
6504
  static void fio_cluster_signal_children(void) {
6500
6505
  if (fio_parent_pid() != getpid()) {
6501
- fio_stop();
6506
+ kill(getpid(), SIGINT);
6502
6507
  return;
6503
6508
  }
6504
6509
  fio_cluster_server_sender(fio_msg_internal_create(0, FIO_CLUSTER_MSG_SHUTDOWN,
@@ -109,8 +109,8 @@ Version and helper macros
109
109
 
110
110
  #define FIO_VERSION_MAJOR 0
111
111
  #define FIO_VERSION_MINOR 7
112
- #define FIO_VERSION_PATCH 0
113
- #define FIO_VERSION_BETA 9
112
+ #define FIO_VERSION_PATCH 3
113
+ #define FIO_VERSION_BETA 0
114
114
 
115
115
  /* Automatically convert version data to a string constant - ignore these two */
116
116
  #define FIO_MACRO2STR_STEP2(macro) #macro
@@ -1250,7 +1250,7 @@ inline FIO_FUNC ssize_t fio_write(const intptr_t uuid, const void *buffer,
1250
1250
  inline FIO_FUNC ssize_t fio_sendfile(intptr_t uuid, intptr_t source_fd,
1251
1251
  off_t offset, size_t length) {
1252
1252
  return fio_write2(uuid, .data.fd = source_fd, .length = length, .is_fd = 1,
1253
- .offset = offset);
1253
+ .offset = (uintptr_t)offset);
1254
1254
  }
1255
1255
 
1256
1256
  /**
@@ -2984,8 +2984,8 @@ FIO_FUNC inline void fio_reschedule_thread(void) {
2984
2984
 
2985
2985
  /** Nanosleep the thread - a blocking throttle. */
2986
2986
  FIO_FUNC inline void fio_throttle_thread(size_t nano_sec) {
2987
- const struct timespec tm = {.tv_nsec = (nano_sec % 1000000000),
2988
- .tv_sec = (nano_sec / 1000000000)};
2987
+ const struct timespec tm = {.tv_nsec = (long)(nano_sec % 1000000000),
2988
+ .tv_sec = (time_t)(nano_sec / 1000000000)};
2989
2989
  nanosleep(&tm, NULL);
2990
2990
  }
2991
2991
 
@@ -5494,10 +5494,10 @@ Done
5494
5494
  * Note: FIO_SET_HASH_TYPE should, normaly be left alone (uintptr_t is
5495
5495
  * enough). Also, the hash value 0 is reserved to indicate an empty slot.
5496
5496
  *
5497
- * Note: the FIO_SET_OBJ_COMPARE for Sets or the FIO_SET_KEY_COMPARE will be
5498
- * used to compare against invalid as well as valid objects. Invalid
5499
- * objects have their bytes all zero. FIO_SET_*_DESTROY should somehow
5500
- * mark them as invalid.
5497
+ * Note: the FIO_SET_OBJ_COMPARE or the FIO_SET_KEY_COMPARE will be used to
5498
+ * compare against invalid as well as valid objects. Invalid objects have
5499
+ * their bytes all zero. FIO_SET_*_DESTROY should somehow mark them as
5500
+ * invalid.
5501
5501
  *
5502
5502
  * Note: Before freeing the Set, FIO_SET_OBJ_DESTROY will be automatically
5503
5503
  * called for every existing object.
@@ -5610,16 +5610,16 @@ typedef struct {
5610
5610
  #endif
5611
5611
 
5612
5612
  /* The default Hash Map-Set has will use straight euqality operators */
5613
- #if !defined(FIO_SET_KEY_COMPARE)
5613
+ #ifndef FIO_SET_KEY_COMPARE
5614
5614
  #define FIO_SET_KEY_COMPARE(o1, o2) ((o1) == (o2))
5615
5615
  #endif
5616
5616
 
5617
5617
  /** Internal macros for object actions in Hash mode */
5618
5618
  #define FIO_SET_COMPARE(o1, o2) FIO_SET_KEY_COMPARE((o1).key, (o2).key)
5619
- #define FIO_SET_COPY(dest, org) \
5619
+ #define FIO_SET_COPY(dest, src) \
5620
5620
  do { \
5621
- FIO_SET_OBJ_COPY((dest).obj, (org).obj); \
5622
- FIO_SET_KEY_COPY((dest).key, (org).key); \
5621
+ FIO_SET_OBJ_COPY((dest).obj, (src).obj); \
5622
+ FIO_SET_KEY_COPY((dest).key, (src).key); \
5623
5623
  } while (0);
5624
5624
  #define FIO_SET_DESTROY(couplet) \
5625
5625
  do { \
@@ -5871,7 +5871,7 @@ FIO_FUNC inline FIO_NAME(_map_s_) *
5871
5871
  if (FIO_SET_HASH_COMPARE(FIO_SET_HASH_INVALID, pos->hash))
5872
5872
  return pos;
5873
5873
  if (FIO_SET_HASH_COMPARE(pos->hash, hash_value_i)) {
5874
- if (!pos->pos || FIO_SET_COMPARE(pos->pos->obj, obj))
5874
+ if (!pos->pos || (FIO_SET_COMPARE(pos->pos->obj, obj)))
5875
5875
  return pos;
5876
5876
  /* full hash value collision detected */
5877
5877
  set->has_collisions = 1;
@@ -5890,7 +5890,7 @@ FIO_FUNC inline FIO_NAME(_map_s_) *
5890
5890
  if (FIO_SET_HASH_COMPARE(FIO_SET_HASH_INVALID, pos->hash))
5891
5891
  return pos;
5892
5892
  if (FIO_SET_HASH_COMPARE(pos->hash, hash_value_i)) {
5893
- if (!pos->pos || FIO_SET_COMPARE(pos->pos->obj, obj))
5893
+ if (!pos->pos || (FIO_SET_COMPARE(pos->pos->obj, obj)))
5894
5894
  return pos;
5895
5895
  /* full hash value collision detected */
5896
5896
  set->has_collisions = 1;
@@ -272,19 +272,19 @@ print_help:
272
272
  switch ((size_t)type) {
273
273
  case FIO_CLI_STRING__TYPE_I:
274
274
  fprintf(stderr,
275
- " \x1B[1m%.*s\x1B[0m\x1B[2m <>\x1B[0m%*s\t\x1B[2msame as "
276
- "%.*s\x1B[0m\n",
275
+ " \x1B[1m%.*s\x1B[0m\x1B[2m <>\x1B[0m%*s\t(same as "
276
+ "\x1B[1m%.*s\x1B[0m)\n",
277
277
  (int)(tmp - start), p + start, padding, "", first_len, p);
278
278
  break;
279
279
  case FIO_CLI_BOOL__TYPE_I:
280
280
  fprintf(stderr,
281
- " \x1B[1m%.*s\x1B[0m %*s\t\x1B[2msame as %.*s\x1B[0m\n",
281
+ " \x1B[1m%.*s\x1B[0m %*s\t(same as \x1B[1m%.*s\x1B[0m)\n",
282
282
  (int)(tmp - start), p + start, padding, "", first_len, p);
283
283
  break;
284
284
  case FIO_CLI_INT__TYPE_I:
285
285
  fprintf(stderr,
286
- " \x1B[1m%.*s\x1B[0m\x1B[2m ##\x1B[0m%*s\t\x1B[2msame as "
287
- "%.*s\x1B[0m\n",
286
+ " \x1B[1m%.*s\x1B[0m\x1B[2m ##\x1B[0m%*s\t(same as "
287
+ "\x1B[1m%.*s\x1B[0m)\n",
288
288
  (int)(tmp - start), p + start, padding, "", first_len, p);
289
289
  break;
290
290
  }
@@ -19,7 +19,7 @@ Feel free to copy, use and enjoy according to the license provided.
19
19
  */
20
20
  #include "fio_tls.h"
21
21
 
22
- #if 1 /* TODO: place library compiler flags here */
22
+ #if !defined(FIO_TLS_FOUND) /* Library compiler flags */
23
23
 
24
24
  #define REQUIRE_LIBRARY()
25
25
  #define FIO_TLS_WEAK
@@ -628,6 +628,7 @@ void FIO_TLS_WEAK fio_tls_destroy(fio_tls_s *tls) {
628
628
  fio_tls_destroy_context(tls);
629
629
  alpn_list_free(&tls->alpn);
630
630
  cert_ary_free(&tls->sni);
631
+ trust_ary_free(&tls->trust);
631
632
  free(tls);
632
633
  }
633
634
 
@@ -1005,6 +1005,7 @@ void FIO_TLS_WEAK fio_tls_destroy(fio_tls_s *tls) {
1005
1005
  fio_tls_destroy_context(tls);
1006
1006
  alpn_list_free(&tls->alpn);
1007
1007
  cert_ary_free(&tls->sni);
1008
+ trust_ary_free(&tls->trust);
1008
1009
  free(tls);
1009
1010
  }
1010
1011
 
@@ -14,7 +14,7 @@ static inline __attribute__((unused)) ssize_t fiobj_send_free(intptr_t uuid,
14
14
  FIOBJ o) {
15
15
  fio_str_info_s s = fiobj_obj2cstr(o);
16
16
  return fio_write2(uuid, .data.buffer = (void *)(o),
17
- .offset = (((intptr_t)s.data) - ((intptr_t)(o))),
17
+ .offset = (uintptr_t)(((intptr_t)s.data) - ((intptr_t)(o))),
18
18
  .length = s.len, .after.dealloc = fiobj4sock_dealloc);
19
19
  }
20
20
 
@@ -82,10 +82,12 @@ size_t fio_ltoa(char *dest, int64_t num, uint8_t base);
82
82
  size_t fio_ftoa(char *dest, double num, uint8_t base);
83
83
 
84
84
  /** Converts a number to a temporary, thread safe, C string object */
85
- fio_str_info_s fio_ltocstr(long);
85
+ fio_str_info_s __attribute__((deprecated("use local buffer with fio_ltoa")))
86
+ fio_ltocstr(long);
86
87
 
87
88
  /** Converts a float to a temporary, thread safe, C string object */
88
- fio_str_info_s fio_ftocstr(double);
89
+ fio_str_info_s __attribute__((deprecated("use local buffer with fio_ftoa")))
90
+ fio_ftocstr(double);
89
91
 
90
92
  /* *****************************************************************************
91
93
  Pointer Wrapping Helper MACROs (uses integers)
@@ -356,6 +356,21 @@ int http_sendfile(http_s *r, int fd, uintptr_t length, uintptr_t offset) {
356
356
  return ((http_vtable_s *)r->private_data.vtbl)
357
357
  ->http_sendfile(r, fd, length, offset);
358
358
  }
359
+
360
+ static inline int http_test_encoded_path(const char *mem, size_t len) {
361
+ const char *pos = NULL;
362
+ const char *end = mem + len;
363
+ while (mem < end && (pos = memchr(mem, '/', (size_t)len))) {
364
+ len = end - pos;
365
+ mem = pos + 1;
366
+ if (pos[1] == '/')
367
+ return -1;
368
+ if (len > 3 && pos[1] == '.' && pos[2] == '.' && pos[3] == '/')
369
+ return -1;
370
+ }
371
+ return 0;
372
+ }
373
+
359
374
  /**
360
375
  * Sends the response headers and the specified file (the response's body).
361
376
  *
@@ -391,14 +406,8 @@ int http_sendfile2(http_s *h, const char *prefix, size_t prefix_len,
391
406
  char *pos = (char *)encoded;
392
407
  const char *end = encoded + encoded_len;
393
408
  while (pos < end) {
394
- /* test for path manipulations while decoding */
395
- if (*pos == '/' && (pos[1] == '/' ||
396
- (((uintptr_t)end - (uintptr_t)pos >= 4) &&
397
- pos[1] == '.' && pos[2] == '.' && pos[3] == '/')))
398
- return -1;
399
409
  if (*pos == '%') {
400
- // decode hex value
401
- // this is a percent encoded value.
410
+ // decode hex value (this is a percent encoded value).
402
411
  if (hex2byte((uint8_t *)tmp.data + tmp.len, (uint8_t *)pos + 1))
403
412
  return -1;
404
413
  tmp.len++;
@@ -408,6 +417,9 @@ int http_sendfile2(http_s *h, const char *prefix, size_t prefix_len,
408
417
  }
409
418
  tmp.data[tmp.len] = 0;
410
419
  fiobj_str_resize(filename, tmp.len);
420
+ /* test for path manipulations after decoding */
421
+ if (http_test_encoded_path(tmp.data + prefix_len, tmp.len - prefix_len))
422
+ return -1;
411
423
  }
412
424
  if (tmp.data[tmp.len - 1] == '/')
413
425
  fiobj_str_write(filename, "index.html", 10);
@@ -370,7 +370,7 @@ struct http_settings_s {
370
370
  * sockets count towards a server's limit.
371
371
  */
372
372
  intptr_t max_clients;
373
- /** reserved for future SSL/TLS support. */
373
+ /** SSL/TLS support. */
374
374
  void *tls;
375
375
  /** reserved for future use. */
376
376
  intptr_t reserved1;
@@ -554,7 +554,7 @@ static int http1_on_request(http1_parser_s *parser) {
554
554
  if (p->request.method && !p->stop)
555
555
  http_finish(&p->request);
556
556
  h1_reset(p);
557
- return !p->close && fio_is_closed(p->p.uuid);
557
+ return fio_is_closed(p->p.uuid);
558
558
  }
559
559
  /** called when a response was received. */
560
560
  static int http1_on_response(http1_parser_s *parser) {
@@ -563,7 +563,7 @@ static int http1_on_response(http1_parser_s *parser) {
563
563
  if (p->request.status_str && !p->stop)
564
564
  http_finish(&p->request);
565
565
  h1_reset(p);
566
- return !p->close && fio_is_closed(p->p.uuid);
566
+ return fio_is_closed(p->p.uuid);
567
567
  }
568
568
  /** called when a request method is parsed. */
569
569
  static int http1_on_method(http1_parser_s *parser, char *method,
@@ -666,9 +666,9 @@ static int http1_on_body_chunk(http1_parser_s *parser, char *data,
666
666
 
667
667
  /** called when a protocol error occurred. */
668
668
  static int http1_on_error(http1_parser_s *parser) {
669
- FIO_LOG_DEBUG("HTTP parser error at HTTP/1.1 buffer position %zu/%zu",
670
- parser->state.next - parser2http(parser)->buf,
671
- parser2http(parser)->buf_len);
669
+ if (parser2http(parser)->close)
670
+ return -1;
671
+ FIO_LOG_DEBUG("HTTP parser error.");
672
672
  fio_close(parser2http(parser)->p.uuid);
673
673
  return -1;
674
674
  }
@@ -723,8 +723,8 @@ static inline void http1_consume_data(intptr_t uuid, http1pr_s *p) {
723
723
 
724
724
  throttle:
725
725
  /* throttle busy clients (slowloris) */
726
- fio_suspend(uuid);
727
726
  p->stop |= 4;
727
+ fio_suspend(uuid);
728
728
  FIO_LOG_DEBUG("(HTTP/1,1) throttling client at %.*s",
729
729
  (int)fio_peer_addr(uuid).len, fio_peer_addr(uuid).data);
730
730
  }
@@ -756,8 +756,8 @@ static void http1_on_close(intptr_t uuid, fio_protocol_s *protocol) {
756
756
  static void http1_on_ready(intptr_t uuid, fio_protocol_s *protocol) {
757
757
  /* resume slow clients from suspension */
758
758
  http1pr_s *p = (http1pr_s *)protocol;
759
- if ((p->stop & 4)) {
760
- p->stop ^= 4;
759
+ if (p->stop & 4) {
760
+ p->stop ^= 4; /* flip back the bit, so it's zero */
761
761
  fio_force_event(uuid, FIO_EVENT_ON_DATA);
762
762
  }
763
763
  (void)protocol;
@@ -776,7 +776,6 @@ static void http1_on_data_first_time(intptr_t uuid, fio_protocol_s *protocol) {
776
776
 
777
777
  /* ensure future reads skip this first time HTTP/2.0 test */
778
778
  p->p.protocol.on_data = http1_on_data;
779
- /* Test fot HTTP/2.0 pre-knowledge */
780
779
  if (i >= 24 && !memcmp(p->buf, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n", 24)) {
781
780
  FIO_LOG_WARNING("client claimed unsupported HTTP/2 prior knowledge.");
782
781
  fio_close(uuid);
@@ -73,6 +73,7 @@ static inline VALUE fiobj_mustache_find_obj_absolute(VALUE udata,
73
73
  /* search by String */
74
74
  key = rb_sym2str(key);
75
75
  tmp = rb_hash_lookup2(udata, key, Qundef);
76
+ rb_str_free(key);
76
77
  if (tmp != Qundef)
77
78
  return tmp;
78
79
  /* search by method */
@@ -295,8 +296,6 @@ static VALUE iodine_mustache_new(int argc, VALUE *argv, VALUE self) {
295
296
  if (filename != Qnil)
296
297
  Check_Type(filename, T_STRING);
297
298
 
298
- fio_str_s str = FIO_STR_INIT;
299
-
300
299
  mustache_s **m = NULL;
301
300
  TypedData_Get_Struct(self, mustache_s *, &iodine_mustache_data_type, m);
302
301
  if (!m) {
@@ -42,5 +42,6 @@ Gem::Specification.new do |spec|
42
42
  spec.add_development_dependency 'minitest', '>=5', '< 6.0'
43
43
  spec.add_development_dependency 'rake-compiler', '>= 1', '< 2.0'
44
44
 
45
- spec.post_install_message = "Thank you for installing Iodine #{Iodine::VERSION}.\n"
45
+ spec.post_install_message = "Thank you for installing Iodine #{Iodine::VERSION}.\n" +
46
+ "Remember: if iodine supports your business, it's is only fair to give value back (code contributions / donations)."
46
47
  end
@@ -9,21 +9,23 @@ module Iodine
9
9
  #
10
10
  # * HTML escaping is more agressive, increasing XSS protection. Read why at: https://wonko.com/post/html-escaping .
11
11
  #
12
- # * Partial template padding in Iodine is adds padding to dynamic text as well as static text. i.e., unlike the official Ruby mustache engine, if an argument contains a new line marker, the new line will be padded to match the partial template padding.
12
+ # * Partial template padding in Iodine adds padding to dynamic text as well as static text, unlike the official Ruby mustache engine. i.e., if an argument contains a new line marker, the new line will be padded to match the partial template padding.
13
13
  #
14
- # * Lambda support is significantly different. For example, the resulting text isn't parsed (no lambda interpolation).
14
+ # * Lambda support is significantly different. For example, the text returned from a lambda isn't parsed (no lambda interpolation).
15
15
  #
16
16
  # * Dot notation is tested in whole as well as in part (i.e. `user.name.first` will be tested as is, than the couplet `"user","name.first"` and than as each `"use","name","first"`), allowing for the Hash data to contain keys with dots while still supporting dot notation shortcuts.
17
17
  #
18
- # * Dot notation supports method names (even chained method names) as long as they don't have or require arguments. For example, `user.class.to_s` will behave differently on Iodine (returns `"String"`) than on the official mustache engine (returns empty string).
18
+ # * Dot notation supports method names (even chained method names) as long as they don't have or require arguments. For example, `user.class.to_s` will behave differently on Iodine (returns call name as `String`) than on the official mustache engine (fails / returns empty string).
19
19
  #
20
- # Iodine Mustache's engine was designed to play best with basic data structures, such as results from the {Iodine::JSON} parser.
20
+ # Iodine Mustache's engine was designed to play best with basic data structures, such as results from the {Iodine::JSON} parser and doesn't require any special classes or types.
21
21
  #
22
22
  # Hash data is tested for Symbol keys before being tested for String keys and methods. This means that `:key` has precedence over `"key"`.
23
23
  #
24
- # Note: Although using methods as "keys" (or argument names) is supported, no Ruby code is evaluated.
24
+ # Note: Although using methods as "keys" (or argument names) is supported, no Ruby code is evaluated. This means that only trusted (pre-existing) code will execute.
25
25
  #
26
- # You can benchmark the Iodine Mustache performance and decide if you wish to switch from the Ruby implementation.
26
+ # Iodine's {Iodine::Mustache} engine performes about 5-7 times faster(!) than the official Ruby mustache engine. Tests performed with Ruby 2.6.0, comparing iodine 0.7.33 against mustache 1.1.0 using a 2.9 GHz Intel Core i9 CPU.
27
+ #
28
+ # You can benchmark the Iodine Mustache performance and decide if you wish to switch from the official Ruby implementation.
27
29
  #
28
30
  # require 'benchmark/ips'
29
31
  # require 'mustache'
@@ -1,3 +1,3 @@
1
1
  module Iodine
2
- VERSION = '0.7.33'.freeze
2
+ VERSION = '0.7.34'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iodine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.33
4
+ version: 0.7.34
5
5
  platform: ruby
6
6
  authors:
7
7
  - Boaz Segev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-07 00:00:00.000000000 Z
11
+ date: 2019-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -202,9 +202,9 @@ licenses:
202
202
  - MIT
203
203
  metadata:
204
204
  allowed_push_host: https://rubygems.org
205
- post_install_message: 'Thank you for installing Iodine 0.7.33.
206
-
207
- '
205
+ post_install_message: |-
206
+ Thank you for installing Iodine 0.7.34.
207
+ Remember: if iodine supports your business, it's is only fair to give value back (code contributions / donations).
208
208
  rdoc_options: []
209
209
  require_paths:
210
210
  - lib