iodine 0.7.33 → 0.7.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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