yajl-ruby 1.4.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: c99601133192fb2ea1f0586ac1b4a83dc465d9a8
4
- data.tar.gz: cbfce4619e6c2ccd5b761bf8d6005dbee6ce043e
2
+ SHA256:
3
+ metadata.gz: dcd3ae6509fd5f45b1527644b221e2ec44e4f697ef0ef5d92399aee3567ad7a6
4
+ data.tar.gz: 0045452d11da4b6b6fbcdf965fd94d0d43655245cb68fca518bfddc38513ad6c
5
5
  SHA512:
6
- metadata.gz: 78c816a3a6368d3b0520d27b5987da10a40478357424e305aa121a6359141ef51c8ee9a3caa4bc3dde159156d5cb6f9af6d5cfd3c576c543b5fd9178ad2993e6
7
- data.tar.gz: fc968516c955984c03c184d11a349c82c109adcce8c590a7537bd291a315bb2a8ac0be92ae927b9458e10dee07b564ebf15806bc591b89b0d09df89b5d6ce173
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
@@ -4,4 +4,9 @@ require 'rbconfig'
4
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
data/ext/yajl/yajl_ext.c CHANGED
@@ -93,7 +93,11 @@ static char *yajl_raise_encode_error_for_status(yajl_gen_status status, VALUE ob
93
93
  rb_raise(cEncodeError, "Invalid number: cannot encode Infinity, -Infinity, or NaN");
94
94
  case yajl_gen_no_buf:
95
95
  rb_raise(cEncodeError, "YAJL internal error: yajl_gen_get_buf was called, but a print callback was specified, so no internal buffer is available");
96
+ case yajl_gen_alloc_error:
97
+ rb_raise(cEncodeError, "YAJL internal error: failed to allocate memory");
96
98
  default:
99
+ // fixme: why wasn't this already here??
100
+ rb_raise(cEncodeError, "Encountered unknown YAJL status %d during JSON generation", status);
97
101
  return NULL;
98
102
  }
99
103
  }
@@ -155,18 +159,47 @@ static void yajl_encoder_wrapper_mark(void * wrapper) {
155
159
  }
156
160
  }
157
161
 
162
+ static VALUE yajl_key_to_string(VALUE obj) {
163
+ switch (TYPE(obj)) {
164
+ case T_STRING:
165
+ return obj;
166
+ case T_SYMBOL:
167
+ return rb_sym2str(obj);
168
+ default:
169
+ return rb_funcall(obj, intern_to_s, 0);
170
+ }
171
+ }
172
+
173
+ void yajl_encode_part(void * wrapper, VALUE obj, VALUE io);
174
+ struct yajl_encode_hash_iter {
175
+ void *w;
176
+ VALUE io;
177
+ };
178
+
179
+ static int yajl_encode_part_hash_i(VALUE key, VALUE val, VALUE iter_v) {
180
+ struct yajl_encode_hash_iter *iter = (struct yajl_encode_hash_iter *)iter_v;
181
+ /* key must be a string */
182
+ VALUE keyStr = yajl_key_to_string(key);
183
+
184
+ /* the key */
185
+ yajl_encode_part(iter->w, keyStr, iter->io);
186
+ /* the value */
187
+ yajl_encode_part(iter->w, val, iter->io);
188
+
189
+ return ST_CONTINUE;
190
+ }
191
+
158
192
  #define CHECK_STATUS(call) \
159
193
  if ((status = (call)) != yajl_gen_status_ok) { break; }
160
194
 
161
195
  void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
162
- VALUE str, outBuff, otherObj;
196
+ VALUE str, outBuff;
163
197
  yajl_encoder_wrapper * w = wrapper;
164
198
  yajl_gen_status status;
165
199
  int idx = 0;
166
200
  const unsigned char * buffer;
167
201
  const char * cptr;
168
202
  unsigned int len;
169
- VALUE keys, entry, keyStr;
170
203
 
171
204
  if (io != Qnil || w->on_progress_callback != Qnil) {
172
205
  status = yajl_gen_get_buf(w->encoder, &buffer, &len);
@@ -188,24 +221,19 @@ void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
188
221
  case T_HASH:
189
222
  CHECK_STATUS(yajl_gen_map_open(w->encoder));
190
223
 
191
- /* TODO: itterate through keys in the hash */
192
- keys = rb_funcall(obj, intern_keys, 0);
193
- for(idx=0; idx<RARRAY_LEN(keys); idx++) {
194
- entry = rb_ary_entry(keys, idx);
195
- keyStr = rb_funcall(entry, intern_to_s, 0); /* key must be a string */
196
- /* the key */
197
- yajl_encode_part(w, keyStr, io);
198
- /* the value */
199
- yajl_encode_part(w, rb_hash_aref(obj, entry), io);
200
- }
224
+ struct yajl_encode_hash_iter iter;
225
+ iter.w = w;
226
+ iter.io = io;
227
+ rb_hash_foreach(obj, yajl_encode_part_hash_i, (VALUE)&iter);
201
228
 
202
229
  CHECK_STATUS(yajl_gen_map_close(w->encoder));
203
230
  break;
204
231
  case T_ARRAY:
205
232
  CHECK_STATUS(yajl_gen_array_open(w->encoder));
233
+
234
+ VALUE *ptr = RARRAY_PTR(obj);
206
235
  for(idx=0; idx<RARRAY_LEN(obj); idx++) {
207
- otherObj = rb_ary_entry(obj, idx);
208
- yajl_encode_part(w, otherObj, io);
236
+ yajl_encode_part(w, ptr[idx], io);
209
237
  }
210
238
  CHECK_STATUS(yajl_gen_array_close(w->encoder));
211
239
  break;
@@ -219,6 +247,8 @@ void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
219
247
  CHECK_STATUS(yajl_gen_bool(w->encoder, 0));
220
248
  break;
221
249
  case T_FIXNUM:
250
+ CHECK_STATUS(yajl_gen_long(w->encoder, FIX2LONG(obj)));
251
+ break;
222
252
  case T_FLOAT:
223
253
  case T_BIGNUM:
224
254
  str = rb_funcall(obj, intern_to_s, 0);
@@ -234,6 +264,12 @@ void yajl_encode_part(void * wrapper, VALUE obj, VALUE io) {
234
264
  len = (unsigned int)RSTRING_LEN(obj);
235
265
  CHECK_STATUS(yajl_gen_string(w->encoder, (const unsigned char *)cptr, len));
236
266
  break;
267
+ case T_SYMBOL:
268
+ str = rb_sym2str(obj);
269
+ cptr = RSTRING_PTR(str);
270
+ len = (unsigned int)RSTRING_LEN(str);
271
+ CHECK_STATUS(yajl_gen_string(w->encoder, (const unsigned char *)cptr, len));
272
+ break;
237
273
  default:
238
274
  if (rb_respond_to(obj, intern_to_json)) {
239
275
  str = rb_funcall(obj, intern_to_json, 0);
@@ -278,11 +314,17 @@ void yajl_parse_chunk(const unsigned char * chunk, unsigned int len, yajl_handle
278
314
 
279
315
  stat = yajl_parse(parser, chunk, len);
280
316
 
281
- if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) {
317
+ if (stat == yajl_status_ok || stat == yajl_status_insufficient_data) {
318
+ // success
319
+ } else if (stat == yajl_status_error) {
282
320
  unsigned char * str = yajl_get_error(parser, 1, chunk, len);
283
321
  VALUE errobj = rb_exc_new2(cParseError, (const char*) str);
284
322
  yajl_free_error(parser, str);
285
323
  rb_exc_raise(errobj);
324
+ } else {
325
+ const char * str = yajl_status_to_string(stat);
326
+ VALUE errobj = rb_exc_new2(cParseError, (const char*) str);
327
+ rb_exc_raise(errobj);
286
328
  }
287
329
  }
288
330
 
@@ -475,13 +517,13 @@ static VALUE rb_yajl_parser_init(int argc, VALUE * argv, VALUE self) {
475
517
  * Document-method: parse
476
518
  *
477
519
  * call-seq:
478
- * parse(input, buffer_size=8092)
479
- * parse(input, buffer_size=8092) { |obj| ... }
520
+ * parse(input, buffer_size=8192)
521
+ * parse(input, buffer_size=8192) { |obj| ... }
480
522
  *
481
523
  * +input+ can either be a string or an IO to parse JSON from
482
524
  *
483
525
  * +buffer_size+ is the size of chunk that will be parsed off the input (if it's an IO) for each loop of the parsing process.
484
- * 8092 is a good balance between the different types of streams (off disk, off a socket, etc...), but this option
526
+ * 8192 is a good balance between the different types of streams (off disk, off a socket, etc...), but this option
485
527
  * is here so the caller can better tune their parsing depending on the type of stream being passed.
486
528
  * A larger read buffer will perform better for files off disk, where as a smaller size may be more efficient for
487
529
  * reading off of a socket directly.
@@ -847,7 +889,7 @@ static VALUE rb_yajl_projector_build_simple_value(yajl_event_stream_t parser, ya
847
889
  case yajl_tok_bool:;
848
890
  if (memcmp(event.buf, "true", 4) == 0) {
849
891
  return Qtrue;
850
- } else if (memcmp(event.buf, "false", 4) == 0) {
892
+ } else if (memcmp(event.buf, "false", 5) == 0) {
851
893
  return Qfalse;
852
894
  } else {
853
895
  rb_raise(cStandardError, "unknown boolean token %s", event.buf);
@@ -884,7 +926,7 @@ static VALUE rb_yajl_projector_build_simple_value(yajl_event_stream_t parser, ya
884
926
  rb_raise(cParseError, "unexpected colon while constructing value");
885
927
 
886
928
  default:;
887
- assert(0);
929
+ rb_bug("we should never get here");
888
930
  }
889
931
  }
890
932
 
@@ -907,6 +949,9 @@ static VALUE rb_yajl_projector_build_string(yajl_event_stream_t parser, yajl_eve
907
949
 
908
950
  yajl_buf strBuf = yajl_buf_alloc(parser->funcs);
909
951
  yajl_string_decode(strBuf, (const unsigned char *)event.buf, event.len);
952
+ if (yajl_buf_err(strBuf)) {
953
+ rb_raise(cParseError, "YAJL internal error: failed to allocate memory");
954
+ }
910
955
 
911
956
  VALUE str = rb_str_new((const char *)yajl_buf_data(strBuf), yajl_buf_len(strBuf));
912
957
  rb_enc_associate(str, utf8Encoding);
@@ -922,7 +967,7 @@ static VALUE rb_yajl_projector_build_string(yajl_event_stream_t parser, yajl_eve
922
967
  }
923
968
 
924
969
  default:; {
925
- assert(0);
970
+ rb_bug("we should never get here");
926
971
  }
927
972
  }
928
973
  }
@@ -1102,6 +1147,7 @@ static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) {
1102
1147
  const unsigned char * buffer;
1103
1148
  unsigned int len;
1104
1149
  VALUE obj, io, blk, outBuff;
1150
+ yajl_gen_status status;
1105
1151
 
1106
1152
  GetEncoder(self, wrapper);
1107
1153
 
@@ -1115,7 +1161,11 @@ static VALUE rb_yajl_encoder_encode(int argc, VALUE * argv, VALUE self) {
1115
1161
  yajl_encode_part(wrapper, obj, io);
1116
1162
 
1117
1163
  /* just make sure we output the remaining buffer */
1118
- yajl_gen_get_buf(wrapper->encoder, &buffer, &len);
1164
+ status = yajl_gen_get_buf(wrapper->encoder, &buffer, &len);
1165
+ if (status != yajl_gen_status_ok) {
1166
+ yajl_raise_encode_error_for_status(status, obj);
1167
+ }
1168
+
1119
1169
  outBuff = rb_str_new((const char *)buffer, len);
1120
1170
  #ifdef HAVE_RUBY_ENCODING_H
1121
1171
  rb_enc_associate(outBuff, utf8Encoding);
data/ext/yajl/yajl_gen.c CHANGED
@@ -178,7 +178,7 @@ yajl_gen_free(yajl_gen g)
178
178
  if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
179
179
 
180
180
  #define DECREMENT_DEPTH \
181
- if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_gen_error;
181
+ if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_depth_underflow;
182
182
 
183
183
  #define APPENDED_ATOM \
184
184
  switch (g->state[g->depth]) { \
@@ -230,6 +230,36 @@ yajl_gen_double(yajl_gen g, double number)
230
230
  return yajl_gen_status_ok;
231
231
  }
232
232
 
233
+ yajl_gen_status
234
+ yajl_gen_long(yajl_gen g, long val)
235
+ {
236
+ char buf[32], *b = buf + sizeof buf;
237
+ unsigned int len = 0;
238
+ unsigned long uval;
239
+
240
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
241
+
242
+ if (val < 0) {
243
+ g->print(g->ctx, "-", 1);
244
+ // Avoid overflow. This shouldn't happen because FIXNUMs are 1 bit less
245
+ // than LONGs, but good to be safe.
246
+ uval = 1 + (unsigned long)(-(val + 1));
247
+ } else {
248
+ uval = val;
249
+ }
250
+
251
+ do {
252
+ *--b = "0123456789"[uval % 10];
253
+ uval /= 10;
254
+ len++;
255
+ } while(uval);
256
+ g->print(g->ctx, b, len);
257
+
258
+ APPENDED_ATOM;
259
+ FINAL_NEWLINE;
260
+ return yajl_gen_status_ok;
261
+ }
262
+
233
263
  yajl_gen_status
234
264
  yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
235
265
  {
@@ -332,6 +362,10 @@ yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
332
362
  unsigned int * len)
333
363
  {
334
364
  if (g->print != (yajl_print_t)&yajl_buf_append) return yajl_gen_no_buf;
365
+ yajl_buf_state buf_err = yajl_buf_err((yajl_buf)g->ctx);
366
+ if (buf_err) {
367
+ return yajl_gen_alloc_error;
368
+ }
335
369
  *buf = yajl_buf_data((yajl_buf)g->ctx);
336
370
  *len = yajl_buf_len((yajl_buf)g->ctx);
337
371
  return yajl_gen_status_ok;
data/ext/yajl/yajl_lex.c CHANGED
@@ -43,6 +43,7 @@ const char *yajl_tok_name(yajl_tok tok) {
43
43
  case yajl_tok_bool: return "bool";
44
44
  case yajl_tok_colon: return "colon";
45
45
  case yajl_tok_comma: return "comma";
46
+ case yajl_tok_comment: return "comment";
46
47
  case yajl_tok_eof: return "eof";
47
48
  case yajl_tok_error: return "error";
48
49
  case yajl_tok_left_brace: return "open_array";
@@ -117,6 +118,8 @@ yajl_lex_alloc(yajl_alloc_funcs * alloc,
117
118
  unsigned int allowComments, unsigned int validateUTF8)
118
119
  {
119
120
  yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
121
+ if (!lxr)
122
+ return NULL;
120
123
  memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
121
124
  lxr->buf = yajl_buf_alloc(alloc);
122
125
  lxr->allowComments = allowComments;
@@ -632,7 +635,12 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
632
635
  lexer->bufInUse = 1;
633
636
  yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset);
634
637
  lexer->bufOff = 0;
635
-
638
+
639
+ if (yajl_buf_err(lexer->buf)) {
640
+ lexer->error = yajl_lex_alloc_failed;
641
+ return yajl_tok_error;
642
+ }
643
+
636
644
  if (tok != yajl_tok_eof) {
637
645
  *outBuf = yajl_buf_data(lexer->buf);
638
646
  *outLen = yajl_buf_len(lexer->buf);
@@ -699,6 +707,8 @@ yajl_lex_error_to_string(yajl_lex_error error)
699
707
  case yajl_lex_unallowed_comment:
700
708
  return "probable comment found in input text, comments are "
701
709
  "not enabled.";
710
+ case yajl_lex_alloc_failed:
711
+ return "allocation failed";
702
712
  }
703
713
  return "unknown error code";
704
714
  }
data/ext/yajl/yajl_lex.h CHANGED
@@ -120,7 +120,8 @@ typedef enum {
120
120
  yajl_lex_missing_integer_after_decimal,
121
121
  yajl_lex_missing_integer_after_exponent,
122
122
  yajl_lex_missing_integer_after_minus,
123
- yajl_lex_unallowed_comment
123
+ yajl_lex_unallowed_comment,
124
+ yajl_lex_alloc_failed
124
125
  } yajl_lex_error;
125
126
 
126
127
  YAJL_API
@@ -134,6 +134,14 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
134
134
  return yajl_status_client_canceled; \
135
135
  }
136
136
 
137
+ /* check for buffer error */
138
+ #define _BUF_CHK(x) \
139
+ if (yajl_buf_err(x)) { \
140
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error); \
141
+ hand->parseError = \
142
+ "allocation failed"; \
143
+ return yajl_status_alloc_failed; \
144
+ }
137
145
 
138
146
  yajl_status
139
147
  yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
@@ -161,7 +169,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
161
169
  /* for arrays and maps, we advance the state for this
162
170
  * depth, then push the state of the next depth.
163
171
  * If an error occurs during the parsing of the nesting
164
- * enitity, the state at this level will not matter.
172
+ * entity, the state at this level will not matter.
165
173
  * a state that needs pushing will be anything other
166
174
  * than state_start */
167
175
  yajl_state stateToPush = yajl_state_start;
@@ -185,6 +193,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
185
193
  if (hand->callbacks && hand->callbacks->yajl_string) {
186
194
  yajl_buf_clear(hand->decodeBuf);
187
195
  yajl_string_decode(hand->decodeBuf, buf, bufLen);
196
+ _BUF_CHK(hand->decodeBuf);
188
197
  _CC_CHK(hand->callbacks->yajl_string(
189
198
  hand->ctx, yajl_buf_data(hand->decodeBuf),
190
199
  yajl_buf_len(hand->decodeBuf)));
@@ -234,6 +243,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
234
243
  long int i = 0;
235
244
  yajl_buf_clear(hand->decodeBuf);
236
245
  yajl_buf_append(hand->decodeBuf, buf, bufLen);
246
+ _BUF_CHK(hand->decodeBuf);
237
247
  buf = yajl_buf_data(hand->decodeBuf);
238
248
  i = strtol((const char *) buf, NULL, 10);
239
249
  if ((i == LONG_MIN || i == LONG_MAX) &&
@@ -261,6 +271,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
261
271
  double d = 0.0;
262
272
  yajl_buf_clear(hand->decodeBuf);
263
273
  yajl_buf_append(hand->decodeBuf, buf, bufLen);
274
+ _BUF_CHK(hand->decodeBuf);
264
275
  buf = yajl_buf_data(hand->decodeBuf);
265
276
  d = strtod((char *) buf, NULL);
266
277
  if ((d == HUGE_VAL || d == -HUGE_VAL) &&
@@ -320,7 +331,9 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
320
331
  }
321
332
  }
322
333
  if (stateToPush != yajl_state_start) {
323
- yajl_bs_push(hand->stateStack, stateToPush);
334
+ if (yajl_bs_push(hand->stateStack, stateToPush)) {
335
+ return yajl_status_alloc_failed;
336
+ }
324
337
  }
325
338
 
326
339
  goto around_again;
@@ -342,6 +355,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText,
342
355
  if (hand->callbacks && hand->callbacks->yajl_map_key) {
343
356
  yajl_buf_clear(hand->decodeBuf);
344
357
  yajl_string_decode(hand->decodeBuf, buf, bufLen);
358
+ _BUF_CHK(hand->decodeBuf);
345
359
  buf = yajl_buf_data(hand->decodeBuf);
346
360
  bufLen = yajl_buf_len(hand->decodeBuf);
347
361
  }
data/lib/yajl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yajl
2
- VERSION = '1.4.1'
2
+ VERSION = '1.4.2'
3
3
  end
@@ -230,6 +230,16 @@ describe "Yajl JSON encoder" do
230
230
  expect(s.read).to eql("{\"foo\":\"bar\"}")
231
231
  end
232
232
 
233
+ it "should encode all integers correctly" do
234
+ 0.upto(129).each do |b|
235
+ b = 1 << b
236
+ [b, b-1, b-2, b+1, b+2].each do |i|
237
+ expect(Yajl::Encoder.encode(i)).to eq(i.to_s)
238
+ expect(Yajl::Encoder.encode(-i)).to eq((-i).to_s)
239
+ end
240
+ end
241
+ end
242
+
233
243
  it "should not encode NaN" do
234
244
  expect {
235
245
  Yajl::Encoder.encode(0.0/0.0)
data/yajl-ruby.gemspec CHANGED
@@ -14,7 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.rubygems_version = %q{1.4.2}
15
15
  s.summary = %q{Ruby C bindings to the excellent Yajl JSON stream-based parser library.}
16
16
  s.test_files = `git ls-files spec examples`.split("\n")
17
- s.required_ruby_version = ">= 1.8.6"
17
+ s.required_ruby_version = ">= 2.6.0"
18
18
 
19
19
  # tests
20
20
  s.add_development_dependency 'rake-compiler'
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yajl-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Lopez
8
8
  - Lloyd Hilaiel
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-07-27 00:00:00.000000000 Z
12
+ date: 2022-04-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
@@ -81,7 +81,7 @@ dependencies:
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
- description:
84
+ description:
85
85
  email: seniorlopez@gmail.com
86
86
  executables: []
87
87
  extensions:
@@ -89,9 +89,9 @@ extensions:
89
89
  extra_rdoc_files: []
90
90
  files:
91
91
  - ".codeclimate.yml"
92
+ - ".github/workflows/ci.yml"
92
93
  - ".gitignore"
93
94
  - ".rspec"
94
- - ".travis.yml"
95
95
  - CHANGELOG.md
96
96
  - Gemfile
97
97
  - LICENSE
@@ -246,7 +246,7 @@ homepage: http://github.com/brianmario/yajl-ruby
246
246
  licenses:
247
247
  - MIT
248
248
  metadata: {}
249
- post_install_message:
249
+ post_install_message:
250
250
  rdoc_options: []
251
251
  require_paths:
252
252
  - lib
@@ -254,16 +254,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
254
254
  requirements:
255
255
  - - ">="
256
256
  - !ruby/object:Gem::Version
257
- version: 1.8.6
257
+ version: 2.6.0
258
258
  required_rubygems_version: !ruby/object:Gem::Requirement
259
259
  requirements:
260
260
  - - ">="
261
261
  - !ruby/object:Gem::Version
262
262
  version: '0'
263
263
  requirements: []
264
- rubyforge_project:
265
- rubygems_version: 2.6.11
266
- signing_key:
264
+ rubygems_version: 3.3.3
265
+ signing_key:
267
266
  specification_version: 4
268
267
  summary: Ruby C bindings to the excellent Yajl JSON stream-based parser library.
269
268
  test_files:
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.0.0
4
- - 2.1
5
- - 2.2
6
- - 2.3
7
- - 2.4.1
8
- - ruby-head
9
- before_install: gem install bundler --no-document