Commit 3ff41ae3 authored by Marc-André Lureau's avatar Marc-André Lureau Committed by Dave Airlie

renderer: fix potential leaks in vrend_create_shader

Found thanks to llvm scan-build.
Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
parent 4f9a3636
...@@ -2135,10 +2135,11 @@ int vrend_create_shader(struct vrend_context *ctx, ...@@ -2135,10 +2135,11 @@ int vrend_create_shader(struct vrend_context *ctx,
const char *shd_text, uint32_t offlen, uint32_t num_tokens, const char *shd_text, uint32_t offlen, uint32_t num_tokens,
uint32_t type, uint32_t pkt_length) uint32_t type, uint32_t pkt_length)
{ {
struct vrend_shader_selector *sel; struct vrend_shader_selector *sel = NULL;
int ret_handle; int ret_handle;
bool new_shader = true, long_shader = false; bool new_shader = true, long_shader = false;
bool finished = false; bool finished = false;
int ret;
if (type > PIPE_SHADER_GEOMETRY) if (type > PIPE_SHADER_GEOMETRY)
return EINVAL; return EINVAL;
...@@ -2166,8 +2167,8 @@ int vrend_create_shader(struct vrend_context *ctx, ...@@ -2166,8 +2167,8 @@ int vrend_create_shader(struct vrend_context *ctx,
sel->buf_len = ((offlen + 3) / 4) * 4; /* round up buffer size */ sel->buf_len = ((offlen + 3) / 4) * 4; /* round up buffer size */
sel->tmp_buf = malloc(sel->buf_len); sel->tmp_buf = malloc(sel->buf_len);
if (!sel->tmp_buf) { if (!sel->tmp_buf) {
free(sel); ret = ENOMEM;
return ENOMEM; goto error;
} }
memcpy(sel->tmp_buf, shd_text, pkt_length * 4); memcpy(sel->tmp_buf, shd_text, pkt_length * 4);
sel->buf_offset = pkt_length * 4; sel->buf_offset = pkt_length * 4;
...@@ -2178,21 +2179,22 @@ int vrend_create_shader(struct vrend_context *ctx, ...@@ -2178,21 +2179,22 @@ int vrend_create_shader(struct vrend_context *ctx,
sel = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SHADER); sel = vrend_object_lookup(ctx->sub->object_hash, handle, VIRGL_OBJECT_SHADER);
if (!sel) { if (!sel) {
fprintf(stderr, "got continuation without original shader %d\n", handle); fprintf(stderr, "got continuation without original shader %d\n", handle);
return EINVAL; ret = EINVAL;
goto error;
} }
offlen &= ~VIRGL_OBJ_SHADER_OFFSET_CONT; offlen &= ~VIRGL_OBJ_SHADER_OFFSET_CONT;
if (offlen != sel->buf_offset) { if (offlen != sel->buf_offset) {
fprintf(stderr, "Got mismatched shader continuation %d vs %d\n", fprintf(stderr, "Got mismatched shader continuation %d vs %d\n",
offlen, sel->buf_offset); offlen, sel->buf_offset);
vrend_renderer_object_destroy(ctx, handle); ret = EINVAL;
return EINVAL; goto error;
} }
if ((pkt_length * 4 + sel->buf_offset) > sel->buf_len) { if ((pkt_length * 4 + sel->buf_offset) > sel->buf_len) {
fprintf(stderr, "Got too large shader continuation %d vs %d\n", fprintf(stderr, "Got too large shader continuation %d vs %d\n",
pkt_length * 4 + sel->buf_offset, sel->buf_len); pkt_length * 4 + sel->buf_offset, sel->buf_len);
vrend_renderer_object_destroy(ctx, handle); ret = EINVAL;
return EINVAL; goto error;
} }
memcpy(sel->tmp_buf + sel->buf_offset, shd_text, pkt_length * 4); memcpy(sel->tmp_buf + sel->buf_offset, shd_text, pkt_length * 4);
...@@ -2209,13 +2211,17 @@ int vrend_create_shader(struct vrend_context *ctx, ...@@ -2209,13 +2211,17 @@ int vrend_create_shader(struct vrend_context *ctx,
tokens = calloc(num_tokens + 10, sizeof(struct tgsi_token)); tokens = calloc(num_tokens + 10, sizeof(struct tgsi_token));
if (!tokens) { if (!tokens) {
return ENOMEM; ret = ENOMEM;
goto error;
} }
if (vrend_dump_shaders) if (vrend_dump_shaders)
fprintf(stderr,"shader\n%s\n", shd_text); fprintf(stderr,"shader\n%s\n", shd_text);
if (!tgsi_text_translate((const char *)shd_text, tokens, num_tokens + 10)) if (!tgsi_text_translate((const char *)shd_text, tokens, num_tokens + 10)) {
return EINVAL; free(tokens);
ret = EINVAL;
goto error;
}
if (vrend_finish_shader(ctx, sel, tokens)) if (vrend_finish_shader(ctx, sel, tokens))
new_shader = false; new_shader = false;
...@@ -2230,13 +2236,20 @@ int vrend_create_shader(struct vrend_context *ctx, ...@@ -2230,13 +2236,20 @@ int vrend_create_shader(struct vrend_context *ctx,
if (new_shader) { if (new_shader) {
ret_handle = vrend_renderer_object_insert(ctx, sel, sizeof(*sel), handle, VIRGL_OBJECT_SHADER); ret_handle = vrend_renderer_object_insert(ctx, sel, sizeof(*sel), handle, VIRGL_OBJECT_SHADER);
if (ret_handle == 0) { if (ret_handle == 0) {
vrend_destroy_shader_selector(sel); ret = ENOMEM;
return ENOMEM; goto error;
} }
} }
return 0; return 0;
error:
if (new_shader)
vrend_destroy_shader_selector(sel);
else
vrend_renderer_object_destroy(ctx, handle);
return ret;
} }
void vrend_bind_shader(struct vrend_context *ctx, void vrend_bind_shader(struct vrend_context *ctx,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment