Node-redis: Data corruption on `get`

Created on 20 Jul 2016  Â·  9Comments  Â·  Source: NodeRedis/node-redis

Found a strange data corruption on get.

Tried with latest redis:3 and redis:2 in docker + node version 6.3.0 and 5.12.0.
Tried to bisect redis package version and found that bug is introduced in version 2.6.0.

Test to reproduce:

const assert = require('assert');

const redis = require('redis').createClient();

const data = JSON.stringify({
    "city_name": "Санкт-Петербург" // (russian language)
});
const key = 'somekey';

describe('redis', () => {

    before(done => redis.set(key, data, done));
    after(done  => redis.del(key, done));

    for (let i = 0; i < 10000; ++i) {
        it(`pass ${i}`, done => {
            redis.get(key, (err, results) => {
                assert(!err);
                assert.strictEqual(results, data);

                done();
            });
        })
    }

});

package.json:

{
  "devDependencies": {
    "mocha": "^2.5.3"
  },
  "dependencies": {
    "redis": "=2.6.0"
  }
}

Output:

    ... (skipped)
    ✓ pass 1217
    ✓ pass 1218
    1) pass 1219
    2) "after all" hook

  1219 passing (4s)
  2 failing

  1) redis pass 1219:

      Uncaught AssertionError: '{"city_name":"��анкт-Петербург"}' === '{"city_name":"Санкт-Петербург"}'
      + expected - actual

      -{"city_name":"��анкт-Петербург"}
      +{"city_name":"Санкт-Петербург"}

Failed pass number is floating. Mocha is running with -b flag to stop on the first fail, but if we test it without this flag, then it will continue to fail after first broken pass:

    ... (skipped)
    ✓ pass 2477
    ✓ pass 2478
    1) pass 2479
    2) pass 2480
    3) pass 2481
    4) pass 2482
    5) pass 2483
    ... (all passes are failed until the end)

First fail is about data corruption, next fails are about err in callback:

{ AbortError: Fatal error encountert. Command aborted. It might have been processed.
    at RedisClient.flush_and_error (/Users/silent/Projects/redis-test/node_modules/redis/index.js:350:23)
    at JavascriptRedisParser.Parser.returnFatalError (/Users/silent/Projects/redis-test/node_modules/redis/index.js:199:18)
    at handleError (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:172:10)
    at parseType (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:224:14)
    at JavascriptRedisParser.execute (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:404:20)
    at Socket.<anonymous> (/Users/silent/Projects/redis-test/node_modules/redis/index.js:267:27)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)
    at readableAddChunk (_stream_readable.js:177:18)
    at Socket.Readable.push (_stream_readable.js:135:10)
    at TCP.onread (net.js:542:20)
  code: 'NR_FATAL',
  command: 'GET',
  args: [ 'somekey' ],
  origin:
   ReplyError: Protocol error, got "c" as reply type byte. Please report this.
       at parseType (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:224:34)
       at JavascriptRedisParser.execute (/Users/silent/Projects/redis-test/node_modules/redis-parser/lib/parser.js:404:20) } undefined

or sometimes with this:

     Uncaught RangeError: out of range index
      at RangeError (native)
      at concatBuffer (node_modules/redis-parser/lib/parser.js:357:13)
      at JavascriptRedisParser.execute (node_modules/redis-parser/lib/parser.js:389:21)
      at Socket.<anonymous> (node_modules/redis/index.js:267:27)
      at readableAddChunk (_stream_readable.js:177:18)
      at Socket.Readable.push (_stream_readable.js:135:10)
      at TCP.onread (net.js:542:20)

Can't reproduce with latin chars only. Also can't reproduce with return_buffers: true.

Here is value via redis-cli, maybe it will be helpful:

127.0.0.1:6379> get somekey
"{\"city_name\":\"\xd0\xa1\xd0\xb0\xd0\xbd\xd0\xba\xd1\x82-\xd0\x9f\xd0\xb5\xd1\x82\xd0\xb5\xd1\x80\xd0\xb1\xd1\x83\xd1\x80\xd0\xb3\"}"
bug fixed / done

All 9 comments

Also reproducable with simple string Санкт-Петербург, without any JSON.{parse,stringify}.

127.0.0.1:6379> get somekey
"\xd0\xa1\xd0\xb0\xd0\xbd\xd0\xba\xd1\x82-\xd0\x9f\xd0\xb5\xd1\x82\xd0\xb5\xd1\x80\xd0\xb1\xd1\x83\xd1\x80\xd0\xb3"

@silentroach what parser version do you currently use? I tried to reproduce this without success.

default parser. here is an archive to reproduce:

test.zip

npm i && npm t

my current node version is 6.3.0, redis version is 3.2.1 (docker run redis), os x

interesting thing - now all the time I run tests (tried about 50 times), the failed iteration number is in always this set 2479, 6260, 7520

Did you try the same without docker?

Hm, tried now and can't reproduce too :(
But can reproduce on production redis server (with first test iteration), that isn't in docker.

Will try to discover differrences.

Can't reproduce on local redis, but can reproduce while connecting to different pc in network with data string modification to more complex example.

test.zip

(just replace host with something different than your ip to work via network)

failed with first iteration, in the next you can find out of range index error.

I just released a new parser version that fixes the issue. I'm sorry about forgetting multi byte characters.

now it is ok, thank you for fast fix!

Thanks for the very good bug report! :+1:

Was this page helpful?
0 / 5 - 0 ratings