read.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
  3. * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * * Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of Redis nor the names of its contributors may be used
  16. * to endorse or promote products derived from this software without
  17. * specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "fmacros.h"
  32. #include <string.h>
  33. #include <stdlib.h>
  34. #ifndef _MSC_VER
  35. #include <unistd.h>
  36. #endif
  37. #include <assert.h>
  38. #include <errno.h>
  39. #include <ctype.h>
  40. #include <limits.h>
  41. #include "read.h"
  42. #include "sds.h"
  43. static void __redisReaderSetError(redisReader *r, int type, const char *str) {
  44. size_t len;
  45. if (r->reply != NULL && r->fn && r->fn->freeObject) {
  46. r->fn->freeObject(r->reply);
  47. r->reply = NULL;
  48. }
  49. /* Clear input buffer on errors. */
  50. sdsfree(r->buf);
  51. r->buf = NULL;
  52. r->pos = r->len = 0;
  53. /* Reset task stack. */
  54. r->ridx = -1;
  55. /* Set error. */
  56. r->err = type;
  57. len = strlen(str);
  58. len = len < (sizeof(r->errstr)-1) ? len : (sizeof(r->errstr)-1);
  59. memcpy(r->errstr,str,len);
  60. r->errstr[len] = '\0';
  61. }
  62. static size_t chrtos(char *buf, size_t size, char byte) {
  63. size_t len = 0;
  64. switch(byte) {
  65. case '\\':
  66. case '"':
  67. len = snprintf(buf,size,"\"\\%c\"",byte);
  68. break;
  69. case '\n': len = snprintf(buf,size,"\"\\n\""); break;
  70. case '\r': len = snprintf(buf,size,"\"\\r\""); break;
  71. case '\t': len = snprintf(buf,size,"\"\\t\""); break;
  72. case '\a': len = snprintf(buf,size,"\"\\a\""); break;
  73. case '\b': len = snprintf(buf,size,"\"\\b\""); break;
  74. default:
  75. if (isprint(byte))
  76. len = snprintf(buf,size,"\"%c\"",byte);
  77. else
  78. len = snprintf(buf,size,"\"\\x%02x\"",(unsigned char)byte);
  79. break;
  80. }
  81. return len;
  82. }
  83. static void __redisReaderSetErrorProtocolByte(redisReader *r, char byte) {
  84. char cbuf[8], sbuf[128];
  85. chrtos(cbuf,sizeof(cbuf),byte);
  86. snprintf(sbuf,sizeof(sbuf),
  87. "Protocol error, got %s as reply type byte", cbuf);
  88. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,sbuf);
  89. }
  90. static void __redisReaderSetErrorOOM(redisReader *r) {
  91. __redisReaderSetError(r,REDIS_ERR_OOM,"Out of memory");
  92. }
  93. static char *readBytes(redisReader *r, unsigned int bytes) {
  94. char *p;
  95. if (r->len-r->pos >= bytes) {
  96. p = r->buf+r->pos;
  97. r->pos += bytes;
  98. return p;
  99. }
  100. return NULL;
  101. }
  102. /* Find pointer to \r\n. */
  103. static char *seekNewline(char *s, size_t len) {
  104. int pos = 0;
  105. int _len = len-1;
  106. /* Position should be < len-1 because the character at "pos" should be
  107. * followed by a \n. Note that strchr cannot be used because it doesn't
  108. * allow to search a limited length and the buffer that is being searched
  109. * might not have a trailing NULL character. */
  110. while (pos < _len) {
  111. while(pos < _len && s[pos] != '\r') pos++;
  112. if (pos==_len) {
  113. /* Not found. */
  114. return NULL;
  115. } else {
  116. if (s[pos+1] == '\n') {
  117. /* Found. */
  118. return s+pos;
  119. } else {
  120. /* Continue searching. */
  121. pos++;
  122. }
  123. }
  124. }
  125. return NULL;
  126. }
  127. /* Convert a string into a long long. Returns REDIS_OK if the string could be
  128. * parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value
  129. * will be set to the parsed value when appropriate.
  130. *
  131. * Note that this function demands that the string strictly represents
  132. * a long long: no spaces or other characters before or after the string
  133. * representing the number are accepted, nor zeroes at the start if not
  134. * for the string "0" representing the zero number.
  135. *
  136. * Because of its strictness, it is safe to use this function to check if
  137. * you can convert a string into a long long, and obtain back the string
  138. * from the number without any loss in the string representation. */
  139. static int string2ll(const char *s, size_t slen, long long *value) {
  140. const char *p = s;
  141. size_t plen = 0;
  142. int negative = 0;
  143. unsigned long long v;
  144. if (plen == slen)
  145. return REDIS_ERR;
  146. /* Special case: first and only digit is 0. */
  147. if (slen == 1 && p[0] == '0') {
  148. if (value != NULL) *value = 0;
  149. return REDIS_OK;
  150. }
  151. if (p[0] == '-') {
  152. negative = 1;
  153. p++; plen++;
  154. /* Abort on only a negative sign. */
  155. if (plen == slen)
  156. return REDIS_ERR;
  157. }
  158. /* First digit should be 1-9, otherwise the string should just be 0. */
  159. if (p[0] >= '1' && p[0] <= '9') {
  160. v = p[0]-'0';
  161. p++; plen++;
  162. } else if (p[0] == '0' && slen == 1) {
  163. *value = 0;
  164. return REDIS_OK;
  165. } else {
  166. return REDIS_ERR;
  167. }
  168. while (plen < slen && p[0] >= '0' && p[0] <= '9') {
  169. if (v > (ULLONG_MAX / 10)) /* Overflow. */
  170. return REDIS_ERR;
  171. v *= 10;
  172. if (v > (ULLONG_MAX - (p[0]-'0'))) /* Overflow. */
  173. return REDIS_ERR;
  174. v += p[0]-'0';
  175. p++; plen++;
  176. }
  177. /* Return if not all bytes were used. */
  178. if (plen < slen)
  179. return REDIS_ERR;
  180. if (negative) {
  181. if (v > ((unsigned long long)(-(LLONG_MIN+1))+1)) /* Overflow. */
  182. return REDIS_ERR;
  183. if (value != NULL) *value = -v;
  184. } else {
  185. if (v > LLONG_MAX) /* Overflow. */
  186. return REDIS_ERR;
  187. if (value != NULL) *value = v;
  188. }
  189. return REDIS_OK;
  190. }
  191. static char *readLine(redisReader *r, int *_len) {
  192. char *p, *s;
  193. int len;
  194. p = r->buf+r->pos;
  195. s = seekNewline(p,(r->len-r->pos));
  196. if (s != NULL) {
  197. len = s-(r->buf+r->pos);
  198. r->pos += len+2; /* skip \r\n */
  199. if (_len) *_len = len;
  200. return p;
  201. }
  202. return NULL;
  203. }
  204. static void moveToNextTask(redisReader *r) {
  205. redisReadTask *cur, *prv;
  206. while (r->ridx >= 0) {
  207. /* Return a.s.a.p. when the stack is now empty. */
  208. if (r->ridx == 0) {
  209. r->ridx--;
  210. return;
  211. }
  212. cur = &(r->rstack[r->ridx]);
  213. prv = &(r->rstack[r->ridx-1]);
  214. assert(prv->type == REDIS_REPLY_ARRAY);
  215. if (cur->idx == prv->elements-1) {
  216. r->ridx--;
  217. } else {
  218. /* Reset the type because the next item can be anything */
  219. assert(cur->idx < prv->elements);
  220. cur->type = -1;
  221. cur->elements = -1;
  222. cur->idx++;
  223. return;
  224. }
  225. }
  226. }
  227. static int processLineItem(redisReader *r) {
  228. redisReadTask *cur = &(r->rstack[r->ridx]);
  229. void *obj;
  230. char *p;
  231. int len;
  232. if ((p = readLine(r,&len)) != NULL) {
  233. if (cur->type == REDIS_REPLY_INTEGER) {
  234. if (r->fn && r->fn->createInteger) {
  235. long long v;
  236. if (string2ll(p, len, &v) == REDIS_ERR) {
  237. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  238. "Bad integer value");
  239. return REDIS_ERR;
  240. }
  241. obj = r->fn->createInteger(cur,v);
  242. } else {
  243. obj = (void*)REDIS_REPLY_INTEGER;
  244. }
  245. } else {
  246. /* Type will be error or status. */
  247. if (r->fn && r->fn->createString)
  248. obj = r->fn->createString(cur,p,len);
  249. else
  250. obj = (void*)(size_t)(cur->type);
  251. }
  252. if (obj == NULL) {
  253. __redisReaderSetErrorOOM(r);
  254. return REDIS_ERR;
  255. }
  256. /* Set reply if this is the root object. */
  257. if (r->ridx == 0) r->reply = obj;
  258. moveToNextTask(r);
  259. return REDIS_OK;
  260. }
  261. return REDIS_ERR;
  262. }
  263. static int processBulkItem(redisReader *r) {
  264. redisReadTask *cur = &(r->rstack[r->ridx]);
  265. void *obj = NULL;
  266. char *p, *s;
  267. long long len;
  268. unsigned long bytelen;
  269. int success = 0;
  270. p = r->buf+r->pos;
  271. s = seekNewline(p,r->len-r->pos);
  272. if (s != NULL) {
  273. p = r->buf+r->pos;
  274. bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
  275. if (string2ll(p, bytelen - 2, &len) == REDIS_ERR) {
  276. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  277. "Bad bulk string length");
  278. return REDIS_ERR;
  279. }
  280. if (len < -1 || (LLONG_MAX > SIZE_MAX && len > (long long)SIZE_MAX)) {
  281. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  282. "Bulk string length out of range");
  283. return REDIS_ERR;
  284. }
  285. if (len == -1) {
  286. /* The nil object can always be created. */
  287. if (r->fn && r->fn->createNil)
  288. obj = r->fn->createNil(cur);
  289. else
  290. obj = (void*)REDIS_REPLY_NIL;
  291. success = 1;
  292. } else {
  293. /* Only continue when the buffer contains the entire bulk item. */
  294. bytelen += len+2; /* include \r\n */
  295. if (r->pos+bytelen <= r->len) {
  296. if (r->fn && r->fn->createString)
  297. obj = r->fn->createString(cur,s+2,len);
  298. else
  299. obj = (void*)REDIS_REPLY_STRING;
  300. success = 1;
  301. }
  302. }
  303. /* Proceed when obj was created. */
  304. if (success) {
  305. if (obj == NULL) {
  306. __redisReaderSetErrorOOM(r);
  307. return REDIS_ERR;
  308. }
  309. r->pos += bytelen;
  310. /* Set reply if this is the root object. */
  311. if (r->ridx == 0) r->reply = obj;
  312. moveToNextTask(r);
  313. return REDIS_OK;
  314. }
  315. }
  316. return REDIS_ERR;
  317. }
  318. static int processMultiBulkItem(redisReader *r) {
  319. redisReadTask *cur = &(r->rstack[r->ridx]);
  320. void *obj;
  321. char *p;
  322. long long elements;
  323. int root = 0, len;
  324. /* Set error for nested multi bulks with depth > 7 */
  325. if (r->ridx == 8) {
  326. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  327. "No support for nested multi bulk replies with depth > 7");
  328. return REDIS_ERR;
  329. }
  330. if ((p = readLine(r,&len)) != NULL) {
  331. if (string2ll(p, len, &elements) == REDIS_ERR) {
  332. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  333. "Bad multi-bulk length");
  334. return REDIS_ERR;
  335. }
  336. root = (r->ridx == 0);
  337. if (elements < -1 || elements > INT_MAX) {
  338. __redisReaderSetError(r,REDIS_ERR_PROTOCOL,
  339. "Multi-bulk length out of range");
  340. return REDIS_ERR;
  341. }
  342. if (elements == -1) {
  343. if (r->fn && r->fn->createNil)
  344. obj = r->fn->createNil(cur);
  345. else
  346. obj = (void*)REDIS_REPLY_NIL;
  347. if (obj == NULL) {
  348. __redisReaderSetErrorOOM(r);
  349. return REDIS_ERR;
  350. }
  351. moveToNextTask(r);
  352. } else {
  353. if (r->fn && r->fn->createArray)
  354. obj = r->fn->createArray(cur,elements);
  355. else
  356. obj = (void*)REDIS_REPLY_ARRAY;
  357. if (obj == NULL) {
  358. __redisReaderSetErrorOOM(r);
  359. return REDIS_ERR;
  360. }
  361. /* Modify task stack when there are more than 0 elements. */
  362. if (elements > 0) {
  363. cur->elements = elements;
  364. cur->obj = obj;
  365. r->ridx++;
  366. r->rstack[r->ridx].type = -1;
  367. r->rstack[r->ridx].elements = -1;
  368. r->rstack[r->ridx].idx = 0;
  369. r->rstack[r->ridx].obj = NULL;
  370. r->rstack[r->ridx].parent = cur;
  371. r->rstack[r->ridx].privdata = r->privdata;
  372. } else {
  373. moveToNextTask(r);
  374. }
  375. }
  376. /* Set reply if this is the root object. */
  377. if (root) r->reply = obj;
  378. return REDIS_OK;
  379. }
  380. return REDIS_ERR;
  381. }
  382. static int processItem(redisReader *r) {
  383. redisReadTask *cur = &(r->rstack[r->ridx]);
  384. char *p;
  385. /* check if we need to read type */
  386. if (cur->type < 0) {
  387. if ((p = readBytes(r,1)) != NULL) {
  388. switch (p[0]) {
  389. case '-':
  390. cur->type = REDIS_REPLY_ERROR;
  391. break;
  392. case '+':
  393. cur->type = REDIS_REPLY_STATUS;
  394. break;
  395. case ':':
  396. cur->type = REDIS_REPLY_INTEGER;
  397. break;
  398. case '$':
  399. cur->type = REDIS_REPLY_STRING;
  400. break;
  401. case '*':
  402. cur->type = REDIS_REPLY_ARRAY;
  403. break;
  404. default:
  405. __redisReaderSetErrorProtocolByte(r,*p);
  406. return REDIS_ERR;
  407. }
  408. } else {
  409. /* could not consume 1 byte */
  410. return REDIS_ERR;
  411. }
  412. }
  413. /* process typed item */
  414. switch(cur->type) {
  415. case REDIS_REPLY_ERROR:
  416. case REDIS_REPLY_STATUS:
  417. case REDIS_REPLY_INTEGER:
  418. return processLineItem(r);
  419. case REDIS_REPLY_STRING:
  420. return processBulkItem(r);
  421. case REDIS_REPLY_ARRAY:
  422. return processMultiBulkItem(r);
  423. default:
  424. assert(NULL);
  425. return REDIS_ERR; /* Avoid warning. */
  426. }
  427. }
  428. redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) {
  429. redisReader *r;
  430. r = calloc(1,sizeof(redisReader));
  431. if (r == NULL)
  432. return NULL;
  433. r->fn = fn;
  434. r->buf = sdsempty();
  435. r->maxbuf = REDIS_READER_MAX_BUF;
  436. if (r->buf == NULL) {
  437. free(r);
  438. return NULL;
  439. }
  440. r->ridx = -1;
  441. return r;
  442. }
  443. void redisReaderFree(redisReader *r) {
  444. if (r == NULL)
  445. return;
  446. if (r->reply != NULL && r->fn && r->fn->freeObject)
  447. r->fn->freeObject(r->reply);
  448. sdsfree(r->buf);
  449. free(r);
  450. }
  451. int redisReaderFeed(redisReader *r, const char *buf, size_t len) {
  452. sds newbuf;
  453. /* Return early when this reader is in an erroneous state. */
  454. if (r->err)
  455. return REDIS_ERR;
  456. /* Copy the provided buffer. */
  457. if (buf != NULL && len >= 1) {
  458. /* Destroy internal buffer when it is empty and is quite large. */
  459. if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) {
  460. sdsfree(r->buf);
  461. r->buf = sdsempty();
  462. r->pos = 0;
  463. /* r->buf should not be NULL since we just free'd a larger one. */
  464. assert(r->buf != NULL);
  465. }
  466. newbuf = sdscatlen(r->buf,buf,len);
  467. if (newbuf == NULL) {
  468. __redisReaderSetErrorOOM(r);
  469. return REDIS_ERR;
  470. }
  471. r->buf = newbuf;
  472. r->len = sdslen(r->buf);
  473. }
  474. return REDIS_OK;
  475. }
  476. int redisReaderGetReply(redisReader *r, void **reply) {
  477. /* Default target pointer to NULL. */
  478. if (reply != NULL)
  479. *reply = NULL;
  480. /* Return early when this reader is in an erroneous state. */
  481. if (r->err)
  482. return REDIS_ERR;
  483. /* When the buffer is empty, there will never be a reply. */
  484. if (r->len == 0)
  485. return REDIS_OK;
  486. /* Set first item to process when the stack is empty. */
  487. if (r->ridx == -1) {
  488. r->rstack[0].type = -1;
  489. r->rstack[0].elements = -1;
  490. r->rstack[0].idx = -1;
  491. r->rstack[0].obj = NULL;
  492. r->rstack[0].parent = NULL;
  493. r->rstack[0].privdata = r->privdata;
  494. r->ridx = 0;
  495. }
  496. /* Process items in reply. */
  497. while (r->ridx >= 0)
  498. if (processItem(r) != REDIS_OK)
  499. break;
  500. /* Return ASAP when an error occurred. */
  501. if (r->err)
  502. return REDIS_ERR;
  503. /* Discard part of the buffer when we've consumed at least 1k, to avoid
  504. * doing unnecessary calls to memmove() in sds.c. */
  505. if (r->pos >= 1024) {
  506. sdsrange(r->buf,r->pos,-1);
  507. r->pos = 0;
  508. r->len = sdslen(r->buf);
  509. }
  510. /* Emit a reply when there is one. */
  511. if (r->ridx == -1) {
  512. if (reply != NULL)
  513. *reply = r->reply;
  514. r->reply = NULL;
  515. }
  516. return REDIS_OK;
  517. }