aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNicolas Hillegeer <nicolas@hillegeer.com>2014-05-31 19:07:38 +0200
committerJustin M. Keyes <justinkz@gmail.com>2014-06-12 01:41:03 -0400
commitebbd87b0be22405c82f2d1dc662241aa284f1622 (patch)
treedbf5c4ff03b9679a7ef4637cf413e8ce7f7ffcb3 /src
parent731761715a89d10b45c0a96340b55e071fe80b20 (diff)
downloadrneovim-ebbd87b0be22405c82f2d1dc662241aa284f1622.tar.gz
rneovim-ebbd87b0be22405c82f2d1dc662241aa284f1622.tar.bz2
rneovim-ebbd87b0be22405c82f2d1dc662241aa284f1622.zip
coverity/62615: fix leak in write_reg_contents_ex
Coverity detected a memory leak caused by not free'ing the value returned by get_expr_line_src (basically vim_strsave(expr_line)). Replaced the copying with direct manipulation of expr_line, since that also happens in other parts of the codebase. NOTE: I'm aware that this has different behaviour than vim_strnsave, namely vim_strnsave always allocates `len` bytes, even if the string is shorter. I don't see how that behaviour is helpful here though.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ops.c105
-rw-r--r--src/nvim/search.c4
2 files changed, 69 insertions, 40 deletions
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 1ee1ce6ecc..67eb6df1bc 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -90,10 +90,10 @@ struct block_def {
colnr_T start_char_vcols; /* number of vcols of pre-block char */
};
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.c.generated.h"
#endif
+
/*
* The names of operators.
* IMPORTANT: Index must correspond with defines in vim.h!!!
@@ -4704,29 +4704,48 @@ get_reg_contents (
return retval;
}
-/*
- * Store string "str" in register "name".
- * "maxlen" is the maximum number of bytes to use, -1 for all bytes.
- * If "must_append" is TRUE, always append to the register. Otherwise append
- * if "name" is an uppercase letter.
- * Note: "maxlen" and "must_append" don't work for the "/" register.
- * Careful: 'str' is modified, you may have to use a copy!
- * If "str" ends in '\n' or '\r', use linewise, otherwise use characterwise.
- */
-void write_reg_contents(int name, char_u *str, int maxlen, int must_append)
+/// write_reg_contents - store `str` in register `name`
+///
+/// @see write_reg_contents_ex
+void write_reg_contents(int name,
+ const char_u *str,
+ ssize_t len,
+ int must_append)
{
- write_reg_contents_ex(name, str, maxlen, must_append, MAUTO, 0L);
+ write_reg_contents_ex(name, str, len, must_append, MAUTO, 0L);
}
-void write_reg_contents_ex(int name, char_u *str, int maxlen, int must_append, int yank_type, long block_len)
+/// write_reg_contents_ex - store `str` in register `name`
+///
+/// If `str` ends in '\n' or '\r', use linewise, otherwise use
+/// characterwise.
+///
+/// @warning when `name` is '/', `len` and `must_append` are ignored. This
+/// means that `str` MUST be NUL-terminated.
+///
+/// @param name The name of the register
+/// @param str The contents to write
+/// @param len If >= 0, write `len` bytes of `str`. Otherwise, write
+/// `strlen(str)` bytes. If `len` is larger than the
+/// allocated size of `src`, the behaviour is undefined.
+/// @param must_append If true, append the contents of `str` to the current
+/// contents of the register. Note that regardless of
+/// `must_append`, this function will append when `name`
+/// is an uppercase letter.
+/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
+/// @param block_len width of visual block
+void write_reg_contents_ex(int name,
+ const char_u *str,
+ ssize_t len,
+ int must_append,
+ int yank_type,
+ long block_len)
{
struct yankreg *old_y_previous, *old_y_current;
- long len;
- if (maxlen >= 0)
- len = maxlen;
- else
- len = (long)STRLEN(str);
+ if (len < 0) {
+ len = (ssize_t) STRLEN(str);
+ }
/* Special case: '/' search pattern */
if (name == '/') {
@@ -4735,17 +4754,25 @@ void write_reg_contents_ex(int name, char_u *str, int maxlen, int must_append, i
}
if (name == '=') {
- char_u *p, *s;
-
- p = vim_strnsave(str, (int)len);
+ size_t offset = 0;
+ size_t totlen = (size_t) len;
- if (must_append) {
- s = concat_str(get_expr_line_src(), p);
- free(p);
- p = s;
+ if (must_append && expr_line) {
+ // append has been specified and expr_line already exists, so we'll
+ // append the new string to expr_line.
+ size_t exprlen = STRLEN(expr_line);
+ totlen += exprlen;
+ offset = exprlen;
}
- set_expr_line(p);
+
+ // modify the global expr_line, extend/shrink it if necessary (realloc).
+ // Copy the input string into the adjusted memory at the specified
+ // offset.
+ expr_line = xrealloc(expr_line, totlen + 1);
+ memcpy(expr_line + offset, str, (size_t) len);
+ expr_line[totlen] = NUL;
+
return;
}
@@ -4773,18 +4800,20 @@ void write_reg_contents_ex(int name, char_u *str, int maxlen, int must_append, i
y_current = old_y_current;
}
-/*
- * Put a string into a register. When the register is not empty, the string
- * is appended.
- */
-static void
-str_to_reg (
- struct yankreg *y_ptr, /* pointer to yank register */
- int yank_type, /* MCHAR, MLINE, MBLOCK, MAUTO */
- char_u *str, /* string to put in register */
- long len, /* length of string */
- long blocklen /* width of Visual block */
-)
+/// str_to_reg - Put a string into a register.
+///
+/// When the register is not empty, the string is appended.
+///
+/// @param y_ptr pointer to yank register
+/// @param yank_type MCHAR, MLINE, MBLOCK or MAUTO
+/// @param str string to put in register
+/// @param len length of the string
+/// @param blocklen width of visual block
+static void str_to_reg(struct yankreg *y_ptr,
+ int yank_type,
+ const char_u *str,
+ long len,
+ long blocklen)
{
int type; /* MCHAR, MLINE or MBLOCK */
int lnum;
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 5ba30eeb00..08fdfa4b63 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -375,14 +375,14 @@ void reset_search_dir(void)
* Set the last search pattern. For ":let @/ =" and viminfo.
* Also set the saved search pattern, so that this works in an autocommand.
*/
-void set_last_search_pat(char_u *s, int idx, int magic, int setlast)
+void set_last_search_pat(const char_u *s, int idx, int magic, int setlast)
{
free(spats[idx].pat);
/* An empty string means that nothing should be matched. */
if (*s == NUL)
spats[idx].pat = NULL;
else
- spats[idx].pat = vim_strsave(s);
+ spats[idx].pat = (char_u *) xstrdup((char *) s);
spats[idx].magic = magic;
spats[idx].no_scs = FALSE;
spats[idx].off.dir = '/';