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.

data/ext/yajl/yajl_ext.h CHANGED
@@ -53,10 +53,10 @@ static rb_encoding *utf8Encoding;
53
53
  #define RARRAY_LEN(s) (RARRAY(s)->len)
54
54
  #endif
55
55
 
56
- static VALUE cParseError, cEncodeError, mYajl, cParser, cEncoder;
56
+ static VALUE cStandardError, cParseError, cEncodeError, mYajl, cParser, cProjector, cEncoder;
57
57
  static ID intern_io_read, intern_call, intern_keys, intern_to_s,
58
58
  intern_to_json, intern_has_key, intern_to_sym, intern_as_json;
59
- static ID sym_allow_comments, sym_check_utf8, sym_pretty, sym_indent, sym_terminator, sym_symbolize_keys, sym_symbolize_names, sym_html_safe;
59
+ static ID sym_allow_comments, sym_check_utf8, sym_pretty, sym_indent, sym_terminator, sym_symbolize_keys, sym_symbolize_names, sym_html_safe, sym_entities;
60
60
 
61
61
  #define GetParser(obj, sval) Data_Get_Struct(obj, yajl_parser_wrapper, sval);
62
62
  #define GetEncoder(obj, sval) Data_Get_Struct(obj, yajl_encoder_wrapper, sval);
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
@@ -38,29 +38,26 @@
38
38
  #include <assert.h>
39
39
  #include <string.h>
40
40
 
41
- #ifdef YAJL_LEXER_DEBUG
42
- static const char *
43
- tokToStr(yajl_tok tok)
44
- {
41
+ const char *yajl_tok_name(yajl_tok tok) {
45
42
  switch (tok) {
46
43
  case yajl_tok_bool: return "bool";
47
44
  case yajl_tok_colon: return "colon";
48
45
  case yajl_tok_comma: return "comma";
46
+ case yajl_tok_comment: return "comment";
49
47
  case yajl_tok_eof: return "eof";
50
48
  case yajl_tok_error: return "error";
51
- case yajl_tok_left_brace: return "brace";
52
- case yajl_tok_left_bracket: return "bracket";
49
+ case yajl_tok_left_brace: return "open_array";
50
+ case yajl_tok_left_bracket: return "open_object";
53
51
  case yajl_tok_null: return "null";
54
52
  case yajl_tok_integer: return "integer";
55
53
  case yajl_tok_double: return "double";
56
- case yajl_tok_right_brace: return "brace";
57
- case yajl_tok_right_bracket: return "bracket";
54
+ case yajl_tok_right_brace: return "close_array";
55
+ case yajl_tok_right_bracket: return "close_object";
58
56
  case yajl_tok_string: return "string";
59
57
  case yajl_tok_string_with_escapes: return "string_with_escapes";
60
58
  }
61
59
  return "unknown";
62
60
  }
63
- #endif
64
61
 
65
62
  /* Impact of the stream parsing feature on the lexer:
66
63
  *
@@ -121,6 +118,8 @@ yajl_lex_alloc(yajl_alloc_funcs * alloc,
121
118
  unsigned int allowComments, unsigned int validateUTF8)
122
119
  {
123
120
  yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
121
+ if (!lxr)
122
+ return NULL;
124
123
  memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
125
124
  lxr->buf = yajl_buf_alloc(alloc);
126
125
  lxr->allowComments = allowComments;
@@ -636,7 +635,12 @@ yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
636
635
  lexer->bufInUse = 1;
637
636
  yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset);
638
637
  lexer->bufOff = 0;
639
-
638
+
639
+ if (yajl_buf_err(lexer->buf)) {
640
+ lexer->error = yajl_lex_alloc_failed;
641
+ return yajl_tok_error;
642
+ }
643
+
640
644
  if (tok != yajl_tok_eof) {
641
645
  *outBuf = yajl_buf_data(lexer->buf);
642
646
  *outLen = yajl_buf_len(lexer->buf);
@@ -703,6 +707,8 @@ yajl_lex_error_to_string(yajl_lex_error error)
703
707
  case yajl_lex_unallowed_comment:
704
708
  return "probable comment found in input text, comments are "
705
709
  "not enabled.";
710
+ case yajl_lex_alloc_failed:
711
+ return "allocation failed";
706
712
  }
707
713
  return "unknown error code";
708
714
  }
@@ -740,6 +746,10 @@ yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
740
746
  tok = yajl_lex_lex(lexer, jsonText, jsonTextLen, &offset,
741
747
  &outBuf, &outLen);
742
748
 
749
+ if (tok == yajl_tok_eof) {
750
+ return tok;
751
+ }
752
+
743
753
  lexer->bufOff = bufOff;
744
754
  lexer->bufInUse = bufInUse;
745
755
  yajl_buf_truncate(lexer->buf, bufLen);
data/ext/yajl/yajl_lex.h CHANGED
@@ -36,33 +36,34 @@
36
36
  #include "api/yajl_common.h"
37
37
 
38
38
  typedef enum {
39
- yajl_tok_bool,
40
- yajl_tok_colon,
41
- yajl_tok_comma,
42
- yajl_tok_eof,
43
- yajl_tok_error,
44
- yajl_tok_left_brace,
45
- yajl_tok_left_bracket,
46
- yajl_tok_null,
47
- yajl_tok_right_brace,
48
- yajl_tok_right_bracket,
39
+ yajl_tok_bool, // 0
40
+ yajl_tok_colon, // 1
41
+ yajl_tok_comma, // 2
42
+ yajl_tok_eof, // 3
43
+ yajl_tok_error, // 4
44
+ yajl_tok_left_brace, // 5
45
+ yajl_tok_left_bracket, // 6
46
+ yajl_tok_null, // 7
47
+ yajl_tok_right_brace, // 8
48
+ yajl_tok_right_bracket, // 9
49
49
 
50
50
  /* we differentiate between integers and doubles to allow the
51
51
  * parser to interpret the number without re-scanning */
52
- yajl_tok_integer,
53
- yajl_tok_double,
52
+ yajl_tok_integer, // 10
53
+ yajl_tok_double, // 11
54
54
 
55
55
  /* we differentiate between strings which require further processing,
56
56
  * and strings that do not */
57
- yajl_tok_string,
58
- yajl_tok_string_with_escapes,
57
+ yajl_tok_string, // 12
58
+ yajl_tok_string_with_escapes, // 13
59
59
 
60
60
  /* comment tokens are not currently returned to the parser, ever */
61
- yajl_tok_comment
61
+ yajl_tok_comment // 14
62
62
  } yajl_tok;
63
63
 
64
64
  typedef struct yajl_lexer_t * yajl_lexer;
65
65
 
66
+ const char *yajl_tok_name(yajl_tok tok);
66
67
 
67
68
  YAJL_API
68
69
  yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc,
@@ -119,7 +120,8 @@ typedef enum {
119
120
  yajl_lex_missing_integer_after_decimal,
120
121
  yajl_lex_missing_integer_after_exponent,
121
122
  yajl_lex_missing_integer_after_minus,
122
- yajl_lex_unallowed_comment
123
+ yajl_lex_unallowed_comment,
124
+ yajl_lex_alloc_failed
123
125
  } yajl_lex_error;
124
126
 
125
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.3.1'
2
+ VERSION = '1.4.2'
3
3
  end
data/lib/yajl.rb CHANGED
@@ -23,6 +23,13 @@ module Yajl
23
23
  Encoder.encode(obj, args, &block)
24
24
  end
25
25
 
26
+ class Projector
27
+ def initialize(stream, read_bufsize=4096)
28
+ @stream = stream
29
+ @buffer_size = read_bufsize
30
+ end
31
+ end
32
+
26
33
  class Parser
27
34
  # A helper method for parse-and-forget use-cases
28
35
  #
@@ -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)
@@ -275,11 +285,27 @@ describe "Yajl JSON encoder" do
275
285
  expect(safe_encoder.encode("</script>")).to eql("\"<\\/script>\"")
276
286
  end
277
287
 
288
+ it "should not encode characters with entities by default" do
289
+ expect(Yajl.dump("\u2028\u2029><&")).to eql("\"\u2028\u2029><&\"")
290
+ end
291
+
292
+ it "should encode characters with entities when enabled" do
293
+ expect(Yajl.dump("\u2028\u2029><&", entities: true)).to eql("\"\\u2028\\u2029\\u003E\\u003C\\u0026\"")
294
+ end
295
+
278
296
  it "should default to *not* escaping / characters" do
279
297
  unsafe_encoder = Yajl::Encoder.new
280
298
  expect(unsafe_encoder.encode("</script>")).not_to eql("\"<\\/script>\"")
281
299
  end
282
300
 
301
+ it "should encode slashes when enabled" do
302
+ unsafe_encoder = Yajl::Encoder.new(:entities => false)
303
+ safe_encoder = Yajl::Encoder.new(:entities => true)
304
+
305
+ expect(unsafe_encoder.encode("</script>")).not_to eql("\"<\\/script>\"")
306
+ expect(safe_encoder.encode("</script>")).to eql("\"\\u003C\\/script\\u003E\"")
307
+ end
308
+
283
309
  it "return value of #to_json must be a string" do
284
310
  expect {
285
311
  Yajl::Encoder.encode(TheMindKiller.new)
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
2
+
3
+ require 'benchmark'
4
+ require 'benchmark/memory'
5
+
6
+ describe "file projection" do
7
+ it "projects file streams" do
8
+ schema = {
9
+ "forced" => nil,
10
+ "created" => nil,
11
+ "pusher" => {
12
+ "name" => nil,
13
+ },
14
+ "repository" => {
15
+ "name" => nil,
16
+ "full_name" => nil,
17
+ },
18
+ "ref" => nil,
19
+ "compare" => nil,
20
+ "commits" => {
21
+ "distinct" => nil,
22
+ "message" => nil,
23
+ "url" => nil,
24
+ "id" => nil,
25
+ "author" => {
26
+ "username" => nil,
27
+ }
28
+ }
29
+ }
30
+
31
+ file_path = ENV['JSON_FILE']
32
+ if file_path.nil? || file_path.empty?
33
+ return
34
+ end
35
+
36
+ Benchmark.memory { |x|
37
+ x.report("project (yajl)") { Yajl::Projector.new(File.open(file_path, 'r')).project(schema) }
38
+ x.compare!
39
+ }
40
+ end
41
+ end