yajl-ruby 1.3.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.

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