yajl-ruby 1.3.1 → 1.4.2

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.

Potentially problematic release.


This version of yajl-ruby might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2211f169082b89b1385a841f79d445cd559b405c
4
- data.tar.gz: 9074ca9bab2acf80a0a7069f2a608ee958b2eea8
2
+ SHA256:
3
+ metadata.gz: dcd3ae6509fd5f45b1527644b221e2ec44e4f697ef0ef5d92399aee3567ad7a6
4
+ data.tar.gz: 0045452d11da4b6b6fbcdf965fd94d0d43655245cb68fca518bfddc38513ad6c
5
5
  SHA512:
6
- metadata.gz: 20f296b807da6097dec709b153364def6cae62187223e64027871103261800e8edda82d5d2bfe96a9dbfb3e29a6b84f56e39c09b45d3bafd423335e86aa52186
7
- data.tar.gz: 89bee3f6029488f771d15a4ebc9e910a8c1ca7d276ef5ad001bb118e7754397bfb4a4065cf5a8b8cc5edffe222bdb669742b6cbe9c6572d3656b3d683393c2b8
6
+ metadata.gz: 4cf495e84d645c644aa62233af8e0498da2b22fdf46f7071694df93af61d7b30785f2d0c1f73932979f92c5f94530427b018fb0bceb94ed5121de0c0fe792b15
7
+ data.tar.gz: bbe72bfd0fd3d0c544557a0bbe7580b5ef33b893ce7df0ef01d40b653d0defdbce963091b9f21fe897082778a3587d9962c4fc10e41bb270c8d32706ef7478b1
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ matrix:
9
+ ruby_version: [2.6.x, 2.7.x, 3.0.x]
10
+ fail-fast: false
11
+ runs-on: ubuntu-latest
12
+ name: Test on Ruby ${{ matrix.ruby_version }}
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Setup Ruby ${{ matrix.ruby_version }}
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby_version }}
19
+ - name: Install dependencies
20
+ run: bundle install
21
+ - name: Build gem
22
+ run: gem build yajl-ruby.gemspec
23
+ - name: Install gem
24
+ run: gem install yajl-ruby
25
+ - name: Run tests
26
+ run: bundle exec rake spec
data/README.md CHANGED
@@ -126,7 +126,7 @@ url = URI.parse("http://search.twitter.com/search.json?q=engineyard")
126
126
  results = Yajl::HttpStream.get(url)
127
127
  ```
128
128
 
129
- Since yajl-ruby parses JSON as a stream, supporting API's like Twitter's Streaming API are a piece-of-cake.
129
+ Since yajl-ruby parses JSON as a stream, supporting APIs like Twitter's Streaming API are a piece-of-cake.
130
130
  You can simply supply a block to `Yajl::HttpStream.get`, which is used as the callback for when a JSON object has been
131
131
  unserialized off the stream. For the case of this Twitter Streaming API call, the callback gets fired a few times a second (depending on your connection speed).
132
132
  The code below is all that's needed to make the request and stream unserialized Ruby hashes off the response, continuously.
@@ -56,6 +56,12 @@ extern "C" {
56
56
  # endif
57
57
  #endif
58
58
 
59
+ #if defined(__GNUC__)
60
+ #define YAJL_WARN_UNUSED __attribute__ ((warn_unused_result))
61
+ #else
62
+ #define YAJL_WARN_UNUSED
63
+ #endif
64
+
59
65
  /** pointer to a malloc function, supporting client overriding memory
60
66
  * allocation routines */
61
67
  typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz);
@@ -63,7 +63,11 @@ extern "C" {
63
63
  yajl_gen_invalid_number,
64
64
  /** A print callback was passed in, so there is no internal
65
65
  * buffer to get from */
66
- yajl_gen_no_buf
66
+ yajl_gen_no_buf,
67
+ /** Tried to decrement at depth 0 */
68
+ yajl_depth_underflow,
69
+ /** Allocation error */
70
+ yajl_gen_alloc_error
67
71
  } yajl_gen_status;
68
72
 
69
73
  /** an opaque handle to a generator */
@@ -129,6 +133,7 @@ extern "C" {
129
133
  * NaN, as these have no representation in JSON. In these cases the
130
134
  * generator will return 'yajl_gen_invalid_number' */
131
135
  YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number);
136
+ YAJL_API yajl_gen_status yajl_gen_long(yajl_gen hand, long value);
132
137
  YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand,
133
138
  const char * num,
134
139
  unsigned int len);
@@ -145,7 +150,7 @@ extern "C" {
145
150
  /** access the null terminated generator buffer. If incrementally
146
151
  * outputing JSON, one should call yajl_gen_clear to clear the
147
152
  * buffer. This allows stream generation. */
148
- YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
153
+ YAJL_API YAJL_WARN_UNUSED yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
149
154
  const unsigned char ** buf,
150
155
  unsigned int * len);
151
156
 
@@ -55,7 +55,9 @@ extern "C" {
55
55
  yajl_status_insufficient_data,
56
56
  /** An error occured during the parse. Call yajl_get_error for
57
57
  * more information about the encountered error */
58
- yajl_status_error
58
+ yajl_status_error,
59
+ /** an allocation failed */
60
+ yajl_status_alloc_failed,
59
61
  } yajl_status;
60
62
 
61
63
  /** attain a human readable, english, string for an error */
data/ext/yajl/extconf.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  require 'mkmf'
2
2
  require 'rbconfig'
3
3
 
4
- $CFLAGS << ' -Wall -funroll-loops'
4
+ $CFLAGS << ' -Wall -funroll-loops -Wno-declaration-after-statement'
5
5
  $CFLAGS << ' -Werror-implicit-function-declaration -Wextra -O0 -ggdb3' if ENV['DEBUG']
6
6
 
7
+ if ENV['SANITIZE']
8
+ $CFLAGS << ' -fsanitize=address'
9
+ $LDFLAGS << ' -fsanitize=address'
10
+ end
11
+
7
12
  create_makefile('yajl/yajl')
data/ext/yajl/yajl.c CHANGED
@@ -56,6 +56,9 @@ yajl_status_to_string(yajl_status stat)
56
56
  case yajl_status_error:
57
57
  statStr = "parse error";
58
58
  break;
59
+ case yajl_status_alloc_failed:
60
+ statStr = "allocation failed";
61
+ break;
59
62
  }
60
63
  return statStr;
61
64
  }
@@ -83,6 +86,8 @@ yajl_alloc(const yajl_callbacks * callbacks,
83
86
  }
84
87
 
85
88
  hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
89
+ if (hand == NULL)
90
+ return NULL;
86
91
 
87
92
  /* copy in pointers to allocation routines */
88
93
  memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
@@ -95,23 +100,31 @@ yajl_alloc(const yajl_callbacks * callbacks,
95
100
  hand->callbacks = callbacks;
96
101
  hand->ctx = ctx;
97
102
  hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
103
+ if (!hand->lexer) {
104
+ YA_FREE(afs, hand);
105
+ return NULL;
106
+ }
98
107
  hand->bytesConsumed = 0;
99
108
  hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
100
109
  yajl_bs_init(hand->stateStack, &(hand->alloc));
101
110
 
102
- yajl_bs_push(hand->stateStack, yajl_state_start);
111
+ if (yajl_bs_push(hand->stateStack, yajl_state_start)) {
112
+ return NULL;
113
+ }
103
114
 
104
115
  return hand;
105
116
  }
106
117
 
107
118
  void
108
119
  yajl_reset_parser(yajl_handle hand) {
120
+ assert(hand);
109
121
  hand->lexer = yajl_lex_realloc(hand->lexer);
110
122
  }
111
123
 
112
124
  void
113
125
  yajl_free(yajl_handle handle)
114
126
  {
127
+ assert(handle);
115
128
  yajl_bs_free(handle->stateStack);
116
129
  yajl_buf_free(handle->decodeBuf);
117
130
  yajl_lex_free(handle->lexer);
@@ -122,6 +135,7 @@ yajl_status
122
135
  yajl_parse(yajl_handle hand, const unsigned char * jsonText,
123
136
  unsigned int jsonTextLen)
124
137
  {
138
+ assert(hand);
125
139
  yajl_status status;
126
140
  status = yajl_do_parse(hand, jsonText, jsonTextLen);
127
141
  return status;
@@ -130,6 +144,7 @@ yajl_parse(yajl_handle hand, const unsigned char * jsonText,
130
144
  yajl_status
131
145
  yajl_parse_complete(yajl_handle hand)
132
146
  {
147
+ assert(hand);
133
148
  /* The particular case we want to handle is a trailing number.
134
149
  * Further input consisting of digits could cause our interpretation
135
150
  * of the number to change (buffered "1" but "2" comes in).
@@ -143,6 +158,7 @@ unsigned char *
143
158
  yajl_get_error(yajl_handle hand, int verbose,
144
159
  const unsigned char * jsonText, unsigned int jsonTextLen)
145
160
  {
161
+ assert(hand);
146
162
  return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose);
147
163
  }
148
164
 
data/ext/yajl/yajl_buf.c CHANGED
@@ -35,43 +35,114 @@
35
35
  #include <assert.h>
36
36
  #include <stdlib.h>
37
37
  #include <string.h>
38
+ #include <stdio.h>
38
39
 
39
40
  #define YAJL_BUF_INIT_SIZE 2048
40
41
 
41
42
  struct yajl_buf_t {
43
+ yajl_buf_state state;
42
44
  unsigned int len;
43
45
  unsigned int used;
44
46
  unsigned char * data;
45
47
  yajl_alloc_funcs * alloc;
46
48
  };
47
49
 
50
+ static void *noop_realloc(void *ctx, void *ptr, unsigned int sz) {
51
+ fprintf(stderr, "Attempt to allocate on invalid yajl_buf_t\n");
52
+ abort();
53
+ }
54
+ static void *noop_malloc(void *ctx, unsigned int sz) { return noop_realloc(ctx, NULL, sz); }
55
+ static void noop_free(void *ctx, void *ptr) { }
56
+
57
+ static yajl_alloc_funcs noop_allocs = {
58
+ .malloc = &noop_malloc,
59
+ .realloc = &noop_realloc,
60
+ .free = &noop_free,
61
+ };
62
+
63
+ // A buffer to be returned if the initial allocation fails
64
+ static struct yajl_buf_t buf_alloc_error = {
65
+ .state = yajl_buf_alloc_failed,
66
+ .alloc = &noop_allocs
67
+ };
68
+
69
+ #include <stdio.h>
70
+
71
+ yajl_buf_state yajl_buf_err(yajl_buf buf)
72
+ {
73
+ assert(buf);
74
+ return buf->state;
75
+ }
76
+
77
+ static
78
+ yajl_buf_state yajl_buf_set_error(yajl_buf buf, yajl_buf_state err)
79
+ {
80
+ buf->state = err;
81
+
82
+ // free and clear all data from the buffer
83
+ YA_FREE(buf->alloc, buf->data);
84
+ buf->len = 0;
85
+ buf->data = 0;
86
+ buf->used = 0;
87
+
88
+ return err;
89
+ }
90
+
48
91
  static
49
- void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
92
+ yajl_buf_state yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
50
93
  {
51
94
  unsigned int need;
52
95
 
53
96
  assert(buf != NULL);
54
97
 
98
+ if (buf->state != yajl_buf_ok) {
99
+ return buf->state;
100
+ }
101
+
55
102
  /* first call */
56
103
  if (buf->data == NULL) {
57
104
  buf->len = YAJL_BUF_INIT_SIZE;
58
105
  buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
106
+ if (buf->data == NULL) {
107
+ return yajl_buf_set_error(buf, yajl_buf_overflow);
108
+ }
109
+
59
110
  buf->data[0] = 0;
60
111
  }
61
112
 
113
+ if (want == 0) {
114
+ return yajl_buf_ok;
115
+ }
116
+
62
117
  need = buf->len;
63
118
 
64
119
  while (want >= (need - buf->used)) need <<= 1;
65
120
 
121
+ // Check for overflow
122
+ if (need < buf->used) {
123
+ return yajl_buf_set_error(buf, yajl_buf_overflow);
124
+ }
125
+
66
126
  if (need != buf->len) {
67
127
  buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
128
+
129
+ if (buf->data == NULL) {
130
+ return yajl_buf_set_error(buf, yajl_buf_overflow);
131
+ }
132
+
68
133
  buf->len = need;
69
134
  }
135
+
136
+ return yajl_buf_ok;
70
137
  }
71
138
 
72
139
  yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
73
140
  {
74
141
  yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
142
+ if (b == NULL) {
143
+ return &buf_alloc_error;
144
+ }
145
+
75
146
  memset((void *) b, 0, sizeof(struct yajl_buf_t));
76
147
  b->alloc = alloc;
77
148
  return b;
@@ -86,7 +157,9 @@ void yajl_buf_free(yajl_buf buf)
86
157
 
87
158
  void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
88
159
  {
89
- yajl_buf_ensure_available(buf, len);
160
+ if (yajl_buf_ensure_available(buf, len)) {
161
+ return;
162
+ }
90
163
  if (len > 0) {
91
164
  assert(data != NULL);
92
165
  memcpy(buf->data + buf->used, data, len);
@@ -97,23 +170,31 @@ void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
97
170
 
98
171
  void yajl_buf_clear(yajl_buf buf)
99
172
  {
173
+ assert(buf);
174
+ assert(!yajl_buf_err(buf));
100
175
  buf->used = 0;
101
176
  if (buf->data) buf->data[buf->used] = 0;
102
177
  }
103
178
 
104
179
  const unsigned char * yajl_buf_data(yajl_buf buf)
105
180
  {
181
+ assert(buf);
182
+ assert(!yajl_buf_err(buf));
106
183
  return buf->data;
107
184
  }
108
185
 
109
186
  unsigned int yajl_buf_len(yajl_buf buf)
110
187
  {
188
+ assert(buf);
189
+ assert(!yajl_buf_err(buf));
111
190
  return buf->used;
112
191
  }
113
192
 
114
193
  void
115
194
  yajl_buf_truncate(yajl_buf buf, unsigned int len)
116
195
  {
196
+ assert(buf);
197
+ assert(!yajl_buf_err(buf));
117
198
  assert(len <= buf->used);
118
199
  buf->used = len;
119
200
  }
data/ext/yajl/yajl_buf.h CHANGED
@@ -43,6 +43,12 @@
43
43
  * call overhead. YMMV.
44
44
  */
45
45
 
46
+ typedef enum {
47
+ yajl_buf_ok = 0,
48
+ yajl_buf_alloc_failed,
49
+ yajl_buf_overflow
50
+ } yajl_buf_state;
51
+
46
52
  /**
47
53
  * yajl_buf is a buffer with exponential growth. the buffer ensures that
48
54
  * you are always null padded.
@@ -77,4 +83,7 @@ unsigned int yajl_buf_len(yajl_buf buf);
77
83
  YAJL_API
78
84
  void yajl_buf_truncate(yajl_buf buf, unsigned int len);
79
85
 
86
+ /* get the state of buffer */
87
+ yajl_buf_state yajl_buf_err(yajl_buf buf);
88
+
80
89
  #endif
@@ -38,9 +38,12 @@
38
38
  #ifndef __YAJL_BYTESTACK_H__
39
39
  #define __YAJL_BYTESTACK_H__
40
40
 
41
+ #include <limits.h>
42
+ #include <assert.h>
41
43
  #include "api/yajl_common.h"
42
44
 
43
45
  #define YAJL_BS_INC 128
46
+ #define YAJL_BS_MAX_SIZE UINT_MAX
44
47
 
45
48
  typedef struct yajl_bytestack_t
46
49
  {
@@ -66,20 +69,34 @@ typedef struct yajl_bytestack_t
66
69
  #define yajl_bs_current(obs) \
67
70
  (assert((obs).used > 0), (obs).stack[(obs).used - 1])
68
71
 
69
- #define yajl_bs_push(obs, byte) { \
70
- if (((obs).size - (obs).used) == 0) { \
71
- (obs).size += YAJL_BS_INC; \
72
- (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,\
73
- (void *) (obs).stack, (obs).size);\
74
- } \
75
- (obs).stack[((obs).used)++] = (byte); \
72
+ /* 0: success, 1: error */
73
+ static inline YAJL_WARN_UNUSED
74
+ int yajl_bs_push_inline(yajl_bytestack *obs, unsigned char byte) {
75
+ if ((obs->size - obs->used) == 0) {
76
+ if (obs->size > YAJL_BS_MAX_SIZE - YAJL_BS_INC)
77
+ return 1;
78
+ obs->size += YAJL_BS_INC;
79
+ obs->stack = obs->yaf->realloc(obs->yaf->ctx, (void *)obs->stack, obs->size);
80
+ if (!obs->stack)
81
+ return 1;
82
+ }
83
+ obs->stack[obs->used++] = byte;
84
+ return 0;
76
85
  }
77
-
86
+
87
+ #define yajl_bs_push(obs, byte) yajl_bs_push_inline(&(obs), (byte))
88
+
78
89
  /* removes the top item of the stack, returns nothing */
79
90
  #define yajl_bs_pop(obs) { ((obs).used)--; }
80
91
 
81
- #define yajl_bs_set(obs, byte) \
82
- (obs).stack[((obs).used) - 1] = (byte);
83
-
92
+ static inline
93
+ void
94
+ yajl_bs_set_inline(yajl_bytestack *obs, unsigned char byte) {
95
+ assert(obs->used > 0);
96
+ assert(obs->size >= obs->used);
97
+ obs->stack[obs->used - 1] = byte;
98
+ }
99
+
100
+ #define yajl_bs_set(obs, byte) yajl_bs_set_inline(&obs, byte)
84
101
 
85
102
  #endif
@@ -59,12 +59,18 @@ yajl_string_encode2(const yajl_print_t print,
59
59
  unsigned int htmlSafe)
60
60
  {
61
61
  unsigned int beg = 0;
62
- unsigned int end = 0;
62
+ unsigned int end = 0;
63
+ unsigned int increment = 0;
63
64
  char hexBuf[7];
65
+ char entityBuffer[7];
64
66
  hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0';
65
67
  hexBuf[6] = 0;
66
68
 
69
+ entityBuffer[0] = '\\'; entityBuffer[1] = 'u'; entityBuffer[2] = '2'; entityBuffer[3] = '0';
70
+ entityBuffer[6] = 0;
71
+
67
72
  while (end < len) {
73
+ increment = 1;
68
74
  const char * escaped = NULL;
69
75
  switch (str[end]) {
70
76
  case '\r': escaped = "\\r"; break;
@@ -76,10 +82,39 @@ yajl_string_encode2(const yajl_print_t print,
76
82
  case '\b': escaped = "\\b"; break;
77
83
  case '\t': escaped = "\\t"; break;
78
84
  case '/':
79
- if (htmlSafe) {
85
+ if (htmlSafe == 1 || htmlSafe == 2) {
80
86
  escaped = "\\/";
81
87
  }
82
88
  break;
89
+ /* Escaping 0xe280a8 0xe280a9 */
90
+ case 0xe2:
91
+ if (htmlSafe == 2) {
92
+ if (len - end >= 2 && str[end + 1] == 0x80) {
93
+ if (str[end + 2] == 0xa8) {
94
+ increment = 3;
95
+ entityBuffer[4] = '2';
96
+ entityBuffer[5] = '8';
97
+ escaped = entityBuffer;
98
+ break;
99
+ }
100
+
101
+ if (str[end + 2] == 0xa9) {
102
+ increment = 3;
103
+ entityBuffer[4] = '2';
104
+ entityBuffer[5] = '9';
105
+ escaped = entityBuffer;
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ case '<':
111
+ case '>':
112
+ case '&':
113
+ if (htmlSafe == 2) {
114
+ CharToHex(str[end], hexBuf + 4);
115
+ escaped = hexBuf;
116
+ }
117
+ break;
83
118
  default:
84
119
  if ((unsigned char) str[end] < 32) {
85
120
  CharToHex(str[end], hexBuf + 4);
@@ -90,7 +125,8 @@ yajl_string_encode2(const yajl_print_t print,
90
125
  if (escaped != NULL) {
91
126
  print(ctx, (const char *) (str + beg), end - beg);
92
127
  print(ctx, escaped, (unsigned int)strlen(escaped));
93
- beg = ++end;
128
+ end += increment;
129
+ beg = end;
94
130
  } else {
95
131
  ++end;
96
132
  }