comparison src/channel.c @ 9246:6ee88fa405b3 v7.4.1906

commit https://github.com/vim/vim/commit/5f1032d2a55b9417a0a6fa225e35089c98a5a419 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Jun 7 22:16:36 2016 +0200 patch 7.4.1906 Problem: Collapsing channel buffers and searching for NL does not work properly. (Xavier de Gary, Ramel Eshed) Solution: Do not assume the buffer contains a NUL or not. Change NUL bytes to NL to avoid the string is truncated.
author Christian Brabandt <cb@256bit.org>
date Tue, 07 Jun 2016 22:30:06 +0200
parents 7d13d180a6ae
children 9f97a6290c63
comparison
equal deleted inserted replaced
9245:fe03dc56fba7 9246:6ee88fa405b3
1548 clear_tv(&rettv); 1548 clear_tv(&rettv);
1549 channel_need_redraw = TRUE; 1549 channel_need_redraw = TRUE;
1550 } 1550 }
1551 1551
1552 /* 1552 /*
1553 * Return the first node from "channel"/"part" without removing it.
1554 * Returns NULL if there is nothing.
1555 */
1556 readq_T *
1557 channel_peek(channel_T *channel, int part)
1558 {
1559 readq_T *head = &channel->ch_part[part].ch_head;
1560
1561 return head->rq_next;
1562 }
1563
1564 /*
1565 * Return a pointer to the first NL in "node".
1566 * Skips over NUL characters.
1567 * Returns NULL if there is no NL.
1568 */
1569 char_u *
1570 channel_first_nl(readq_T *node)
1571 {
1572 char_u *buffer = node->rq_buffer;
1573 long_u i;
1574
1575 for (i = 0; i < node->rq_buflen; ++i)
1576 if (buffer[i] == NL)
1577 return buffer + i;
1578 return NULL;
1579 }
1580
1581 /*
1553 * Return the first buffer from channel "channel"/"part" and remove it. 1582 * Return the first buffer from channel "channel"/"part" and remove it.
1554 * The caller must free it. 1583 * The caller must free it.
1555 * Returns NULL if there is nothing. 1584 * Returns NULL if there is nothing.
1556 */ 1585 */
1557 char_u * 1586 char_u *
1574 return p; 1603 return p;
1575 } 1604 }
1576 1605
1577 /* 1606 /*
1578 * Returns the whole buffer contents concatenated for "channel"/"part". 1607 * Returns the whole buffer contents concatenated for "channel"/"part".
1608 * Replaces NUL bytes with NL.
1579 */ 1609 */
1580 static char_u * 1610 static char_u *
1581 channel_get_all(channel_T *channel, int part) 1611 channel_get_all(channel_T *channel, int part)
1582 { 1612 {
1583 readq_T *head = &channel->ch_part[part].ch_head; 1613 readq_T *head = &channel->ch_part[part].ch_head;
1597 if (res == NULL) 1627 if (res == NULL)
1598 return NULL; 1628 return NULL;
1599 p = res; 1629 p = res;
1600 for (node = head->rq_next; node != NULL; node = node->rq_next) 1630 for (node = head->rq_next; node != NULL; node = node->rq_next)
1601 { 1631 {
1602 STRCPY(p, node->rq_buffer); 1632 mch_memmove(p, node->rq_buffer, node->rq_buflen);
1603 p += node->rq_buflen; 1633 p += node->rq_buflen;
1604 } 1634 }
1605 *p = NUL; 1635 *p = NUL;
1606 1636
1607 /* Free all buffers */ 1637 /* Free all buffers */
1609 { 1639 {
1610 p = channel_get(channel, part); 1640 p = channel_get(channel, part);
1611 vim_free(p); 1641 vim_free(p);
1612 } while (p != NULL); 1642 } while (p != NULL);
1613 1643
1644 /* turn all NUL into NL */
1645 while (len > 0)
1646 {
1647 --len;
1648 if (res[len] == NUL)
1649 res[len] = NL;
1650 }
1651
1614 return res; 1652 return res;
1653 }
1654
1655 /*
1656 * Consume "len" bytes from the head of "channel"/"part".
1657 * Caller must check these bytes are available.
1658 */
1659 void
1660 channel_consume(channel_T *channel, int part, int len)
1661 {
1662 readq_T *head = &channel->ch_part[part].ch_head;
1663 readq_T *node = head->rq_next;
1664 char_u *buf = node->rq_buffer;
1665
1666 mch_memmove(buf, buf + len, node->rq_buflen - len);
1667 node->rq_buflen -= len;
1615 } 1668 }
1616 1669
1617 /* 1670 /*
1618 * Collapses the first and second buffer for "channel"/"part". 1671 * Collapses the first and second buffer for "channel"/"part".
1619 * Returns FAIL if that is not possible. 1672 * Returns FAIL if that is not possible.
1635 1688
1636 last_node = node->rq_next; 1689 last_node = node->rq_next;
1637 len = node->rq_buflen + last_node->rq_buflen + 1; 1690 len = node->rq_buflen + last_node->rq_buflen + 1;
1638 if (want_nl) 1691 if (want_nl)
1639 while (last_node->rq_next != NULL 1692 while (last_node->rq_next != NULL
1640 && vim_strchr(last_node->rq_buffer, NL) == NULL) 1693 && channel_first_nl(last_node) == NULL)
1641 { 1694 {
1642 last_node = last_node->rq_next; 1695 last_node = last_node->rq_next;
1643 len += last_node->rq_buflen; 1696 len += last_node->rq_buflen;
1644 } 1697 }
1645 1698
1646 p = newbuf = alloc(len); 1699 p = newbuf = alloc(len);
1647 if (newbuf == NULL) 1700 if (newbuf == NULL)
1648 return FAIL; /* out of memory */ 1701 return FAIL; /* out of memory */
1649 STRCPY(p, node->rq_buffer); 1702 mch_memmove(p, node->rq_buffer, node->rq_buflen);
1650 p += node->rq_buflen; 1703 p += node->rq_buflen;
1651 vim_free(node->rq_buffer); 1704 vim_free(node->rq_buffer);
1652 node->rq_buffer = newbuf; 1705 node->rq_buffer = newbuf;
1653 for (n = node; n != last_node; ) 1706 for (n = node; n != last_node; )
1654 { 1707 {
1655 n = n->rq_next; 1708 n = n->rq_next;
1656 STRCPY(p, n->rq_buffer); 1709 mch_memmove(p, n->rq_buffer, n->rq_buflen);
1657 p += n->rq_buflen; 1710 p += n->rq_buflen;
1658 vim_free(n->rq_buffer); 1711 vim_free(n->rq_buffer);
1659 } 1712 }
1660 node->rq_buflen = (long_u)(p - newbuf); 1713 node->rq_buflen = (long_u)(p - newbuf);
1661 1714
1689 int i; 1742 int i;
1690 1743
1691 node = (readq_T *)alloc(sizeof(readq_T)); 1744 node = (readq_T *)alloc(sizeof(readq_T));
1692 if (node == NULL) 1745 if (node == NULL)
1693 return FAIL; /* out of memory */ 1746 return FAIL; /* out of memory */
1747 /* A NUL is added at the end, because netbeans code expects that.
1748 * Otherwise a NUL may appear inside the text. */
1694 node->rq_buffer = alloc(len + 1); 1749 node->rq_buffer = alloc(len + 1);
1695 if (node->rq_buffer == NULL) 1750 if (node->rq_buffer == NULL)
1696 { 1751 {
1697 vim_free(node); 1752 vim_free(node);
1698 return FAIL; /* out of memory */ 1753 return FAIL; /* out of memory */
2281 cbq_T *cbhead = &channel->ch_part[part].ch_cb_head; 2336 cbq_T *cbhead = &channel->ch_part[part].ch_cb_head;
2282 cbq_T *cbitem; 2337 cbq_T *cbitem;
2283 char_u *callback = NULL; 2338 char_u *callback = NULL;
2284 partial_T *partial = NULL; 2339 partial_T *partial = NULL;
2285 buf_T *buffer = NULL; 2340 buf_T *buffer = NULL;
2341 char_u *p;
2286 2342
2287 if (channel->ch_nb_close_cb != NULL) 2343 if (channel->ch_nb_close_cb != NULL)
2288 /* this channel is handled elsewhere (netbeans) */ 2344 /* this channel is handled elsewhere (netbeans) */
2289 return FALSE; 2345 return FALSE;
2290 2346
2373 2429
2374 if (ch_mode == MODE_NL) 2430 if (ch_mode == MODE_NL)
2375 { 2431 {
2376 char_u *nl; 2432 char_u *nl;
2377 char_u *buf; 2433 char_u *buf;
2434 readq_T *node;
2378 2435
2379 /* See if we have a message ending in NL in the first buffer. If 2436 /* See if we have a message ending in NL in the first buffer. If
2380 * not try to concatenate the first and the second buffer. */ 2437 * not try to concatenate the first and the second buffer. */
2381 while (TRUE) 2438 while (TRUE)
2382 { 2439 {
2383 buf = channel_peek(channel, part); 2440 node = channel_peek(channel, part);
2384 nl = vim_strchr(buf, NL); 2441 nl = channel_first_nl(node);
2385 if (nl != NULL) 2442 if (nl != NULL)
2386 break; 2443 break;
2387 if (channel_collapse(channel, part, TRUE) == FAIL) 2444 if (channel_collapse(channel, part, TRUE) == FAIL)
2388 return FALSE; /* incomplete message */ 2445 return FALSE; /* incomplete message */
2389 } 2446 }
2390 if (nl[1] == NUL) 2447 buf = node->rq_buffer;
2448
2449 /* Convert NUL to NL, the internal representation. */
2450 for (p = buf; p < nl && p < buf + node->rq_buflen; ++p)
2451 if (*p == NUL)
2452 *p = NL;
2453
2454 if (nl + 1 == buf + node->rq_buflen)
2391 { 2455 {
2392 /* get the whole buffer, drop the NL */ 2456 /* get the whole buffer, drop the NL */
2393 msg = channel_get(channel, part); 2457 msg = channel_get(channel, part);
2394 *nl = NUL; 2458 *nl = NUL;
2395 } 2459 }
2396 else 2460 else
2397 { 2461 {
2398 /* Copy the message into allocated memory and remove it from 2462 /* Copy the message into allocated memory (excluding the NL)
2399 * the buffer. */ 2463 * and remove it from the buffer (including the NL). */
2400 msg = vim_strnsave(buf, (int)(nl - buf)); 2464 msg = vim_strnsave(buf, (int)(nl - buf));
2401 mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1); 2465 channel_consume(channel, part, (int)(nl - buf) + 1);
2402 } 2466 }
2403 } 2467 }
2404 else 2468 else
2469 {
2405 /* For a raw channel we don't know where the message ends, just 2470 /* For a raw channel we don't know where the message ends, just
2406 * get everything we have. */ 2471 * get everything we have.
2472 * Convert NUL to NL, the internal representation. */
2407 msg = channel_get_all(channel, part); 2473 msg = channel_get_all(channel, part);
2474 }
2408 2475
2409 if (msg == NULL) 2476 if (msg == NULL)
2410 return FALSE; /* out of memory (and avoids Coverity warning) */ 2477 return FALSE; /* out of memory (and avoids Coverity warning) */
2411 2478
2412 argv[1].v_type = VAR_STRING; 2479 argv[1].v_type = VAR_STRING;
2663 for (part = PART_SOCK; part <= PART_ERR; ++part) 2730 for (part = PART_SOCK; part <= PART_ERR; ++part)
2664 drop_messages(channel, part); 2731 drop_messages(channel, part);
2665 } 2732 }
2666 2733
2667 channel->ch_nb_close_cb = NULL; 2734 channel->ch_nb_close_cb = NULL;
2668 }
2669
2670 /*
2671 * Return the first buffer from "channel"/"part" without removing it.
2672 * Returns NULL if there is nothing.
2673 */
2674 char_u *
2675 channel_peek(channel_T *channel, int part)
2676 {
2677 readq_T *head = &channel->ch_part[part].ch_head;
2678
2679 if (head->rq_next == NULL)
2680 return NULL;
2681 return head->rq_next->rq_buffer;
2682 } 2735 }
2683 2736
2684 /* 2737 /*
2685 * Clear the read buffer on "channel"/"part". 2738 * Clear the read buffer on "channel"/"part".
2686 */ 2739 */
3041 char_u *buf; 3094 char_u *buf;
3042 char_u *msg; 3095 char_u *msg;
3043 ch_mode_T mode = channel->ch_part[part].ch_mode; 3096 ch_mode_T mode = channel->ch_part[part].ch_mode;
3044 sock_T fd = channel->ch_part[part].ch_fd; 3097 sock_T fd = channel->ch_part[part].ch_fd;
3045 char_u *nl; 3098 char_u *nl;
3099 readq_T *node;
3046 3100
3047 ch_logsn(channel, "Blocking %s read, timeout: %d msec", 3101 ch_logsn(channel, "Blocking %s read, timeout: %d msec",
3048 mode == MODE_RAW ? "RAW" : "NL", timeout); 3102 mode == MODE_RAW ? "RAW" : "NL", timeout);
3049 3103
3050 while (TRUE) 3104 while (TRUE)
3051 { 3105 {
3052 buf = channel_peek(channel, part); 3106 node = channel_peek(channel, part);
3053 if (buf != NULL && (mode == MODE_RAW 3107 if (node != NULL)
3054 || (mode == MODE_NL && vim_strchr(buf, NL) != NULL))) 3108 {
3055 break; 3109 if (mode == MODE_RAW || (mode == MODE_NL
3056 if (buf != NULL && channel_collapse(channel, part, mode == MODE_NL) 3110 && channel_first_nl(node) != NULL))
3057 == OK) 3111 /* got a complete message */
3058 continue; 3112 break;
3113 if (channel_collapse(channel, part, mode == MODE_NL) == OK)
3114 continue;
3115 }
3059 3116
3060 /* Wait for up to the channel timeout. */ 3117 /* Wait for up to the channel timeout. */
3061 if (fd == INVALID_FD) 3118 if (fd == INVALID_FD)
3062 return NULL; 3119 return NULL;
3063 if (channel_wait(channel, fd, timeout) != CW_READY) 3120 if (channel_wait(channel, fd, timeout) != CW_READY)
3072 { 3129 {
3073 msg = channel_get_all(channel, part); 3130 msg = channel_get_all(channel, part);
3074 } 3131 }
3075 else 3132 else
3076 { 3133 {
3077 nl = vim_strchr(buf, NL); 3134 char_u *p;
3078 if (nl[1] == NUL) 3135
3136 buf = node->rq_buffer;
3137 nl = channel_first_nl(node);
3138
3139 /* Convert NUL to NL, the internal representation. */
3140 for (p = buf; p < nl && p < buf + node->rq_buflen; ++p)
3141 if (*p == NUL)
3142 *p = NL;
3143
3144 if (nl + 1 == buf + node->rq_buflen)
3079 { 3145 {
3080 /* get the whole buffer */ 3146 /* get the whole buffer */
3081 msg = channel_get(channel, part); 3147 msg = channel_get(channel, part);
3082 *nl = NUL; 3148 *nl = NUL;
3083 } 3149 }
3084 else 3150 else
3085 { 3151 {
3086 /* Copy the message into allocated memory and remove it from the 3152 /* Copy the message into allocated memory and remove it from the
3087 * buffer. */ 3153 * buffer. */
3088 msg = vim_strnsave(buf, (int)(nl - buf)); 3154 msg = vim_strnsave(buf, (int)(nl - buf));
3089 mch_memmove(buf, nl + 1, STRLEN(nl + 1) + 1); 3155 channel_consume(channel, part, (int)(nl - buf) + 1);
3090 } 3156 }
3091 } 3157 }
3092 if (log_fd != NULL) 3158 if (log_fd != NULL)
3093 ch_logn(channel, "Returning %d bytes", (int)STRLEN(msg)); 3159 ch_logn(channel, "Returning %d bytes", (int)STRLEN(msg));
3094 return msg; 3160 return msg;