qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

vnc: fix memory leak when vnc disconnect

Currently when qemu receives a vnc connect, it creates a 'VncState' to
represent this connection. In 'vnc_worker_thread_loop' it creates a
local 'VncState'. The connection 'VcnState' and local 'VncState' exchange
data in 'vnc_async_encoding_start' and 'vnc_async_encoding_end'.
In 'zrle_compress_data' it calls 'deflateInit2' to allocate the libz library
opaque data. The 'VncState' used in 'zrle_compress_data' is the local
'VncState'. In 'vnc_zrle_clear' it calls 'deflateEnd' to free the libz
library opaque data. The 'VncState' used in 'vnc_zrle_clear' is the connection
'VncState'. In currently implementation there will be a memory leak when the
vnc disconnect. Following is the asan output backtrack:

Direct leak of 29760 byte(s) in 5 object(s) allocated from:
0 0xffffa67ef3c3 in __interceptor_calloc (/lib64/libasan.so.4+0xd33c3)
1 0xffffa65071cb in g_malloc0 (/lib64/libglib-2.0.so.0+0x571cb)
2 0xffffa5e968f7 in deflateInit2_ (/lib64/libz.so.1+0x78f7)
3 0xaaaacec58613 in zrle_compress_data ui/vnc-enc-zrle.c:87
4 0xaaaacec58613 in zrle_send_framebuffer_update ui/vnc-enc-zrle.c:344
5 0xaaaacec34e77 in vnc_send_framebuffer_update ui/vnc.c:919
6 0xaaaacec5e023 in vnc_worker_thread_loop ui/vnc-jobs.c:271
7 0xaaaacec5e5e7 in vnc_worker_thread ui/vnc-jobs.c:340
8 0xaaaacee4d3c3 in qemu_thread_start util/qemu-thread-posix.c:502
9 0xffffa544e8bb in start_thread (/lib64/libpthread.so.0+0x78bb)
10 0xffffa53965cb in thread_start (/lib64/libc.so.6+0xd55cb)

This is because the opaque allocated in 'deflateInit2' is not freed in
'deflateEnd'. The reason is that the 'deflateEnd' calls 'deflateStateCheck'
and in the latter will check whether 's->strm != strm'(libz's data structure).
This check will be true so in 'deflateEnd' it just return 'Z_STREAM_ERROR' and
not free the data allocated in 'deflateInit2'.

The reason this happens is that the 'VncState' contains the whole 'VncZrle',
so when calling 'deflateInit2', the 's->strm' will be the local address.
So 's->strm != strm' will be true.

To fix this issue, we need to make 'zrle' of 'VncState' to be a pointer.
Then the connection 'VncState' and local 'VncState' exchange mechanism will
work as expection. The 'tight' of 'VncState' has the same issue, let's also turn
it to a pointer.

Reported-by: Ying Fang <fangying1@huawei.com>
Signed-off-by: Li Qiang <liq3ea@163.com>
Message-id: 20190831153922.121308-1-liq3ea@163.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Li Qiang and committed by
Gerd Hoffmann
6bf21f3d 6105683d

+170 -162
+111 -108
ui/vnc-enc-tight.c
··· 116 116 117 117 static bool tight_can_send_png_rect(VncState *vs, int w, int h) 118 118 { 119 - if (vs->tight.type != VNC_ENCODING_TIGHT_PNG) { 119 + if (vs->tight->type != VNC_ENCODING_TIGHT_PNG) { 120 120 return false; 121 121 } 122 122 ··· 144 144 int pixels = 0; 145 145 int pix, left[3]; 146 146 unsigned int errors; 147 - unsigned char *buf = vs->tight.tight.buffer; 147 + unsigned char *buf = vs->tight->tight.buffer; 148 148 149 149 /* 150 150 * If client is big-endian, color samples begin from the second ··· 215 215 int pixels = 0; \ 216 216 int sample, sum, left[3]; \ 217 217 unsigned int errors; \ 218 - unsigned char *buf = vs->tight.tight.buffer; \ 218 + unsigned char *buf = vs->tight->tight.buffer; \ 219 219 \ 220 220 endian = 0; /* FIXME */ \ 221 221 \ ··· 296 296 tight_detect_smooth_image(VncState *vs, int w, int h) 297 297 { 298 298 unsigned int errors; 299 - int compression = vs->tight.compression; 300 - int quality = vs->tight.quality; 299 + int compression = vs->tight->compression; 300 + int quality = vs->tight->quality; 301 301 302 302 if (!vs->vd->lossy) { 303 303 return 0; ··· 309 309 return 0; 310 310 } 311 311 312 - if (vs->tight.quality != (uint8_t)-1) { 312 + if (vs->tight->quality != (uint8_t)-1) { 313 313 if (w * h < VNC_TIGHT_JPEG_MIN_RECT_SIZE) { 314 314 return 0; 315 315 } ··· 320 320 } 321 321 322 322 if (vs->client_pf.bytes_per_pixel == 4) { 323 - if (vs->tight.pixel24) { 323 + if (vs->tight->pixel24) { 324 324 errors = tight_detect_smooth_image24(vs, w, h); 325 - if (vs->tight.quality != (uint8_t)-1) { 325 + if (vs->tight->quality != (uint8_t)-1) { 326 326 return (errors < tight_conf[quality].jpeg_threshold24); 327 327 } 328 328 return (errors < tight_conf[compression].gradient_threshold24); ··· 352 352 uint##bpp##_t c0, c1, ci; \ 353 353 int i, n0, n1; \ 354 354 \ 355 - data = (uint##bpp##_t *)vs->tight.tight.buffer; \ 355 + data = (uint##bpp##_t *)vs->tight->tight.buffer; \ 356 356 \ 357 357 c0 = data[0]; \ 358 358 i = 1; \ ··· 423 423 { 424 424 int max; 425 425 426 - max = count / tight_conf[vs->tight.compression].idx_max_colors_divisor; 426 + max = count / tight_conf[vs->tight->compression].idx_max_colors_divisor; 427 427 if (max < 2 && 428 - count >= tight_conf[vs->tight.compression].mono_min_rect_size) { 428 + count >= tight_conf[vs->tight->compression].mono_min_rect_size) { 429 429 max = 2; 430 430 } 431 431 if (max >= 256) { ··· 558 558 int x, y, c; 559 559 560 560 buf32 = (uint32_t *)buf; 561 - memset(vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); 561 + memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); 562 562 563 563 if (1 /* FIXME */) { 564 564 shift[0] = vs->client_pf.rshift; ··· 575 575 upper[c] = 0; 576 576 here[c] = 0; 577 577 } 578 - prev = (int *)vs->tight.gradient.buffer; 578 + prev = (int *)vs->tight->gradient.buffer; 579 579 for (x = 0; x < w; x++) { 580 580 pix32 = *buf32++; 581 581 for (c = 0; c < 3; c++) { ··· 615 615 int prediction; \ 616 616 int x, y, c; \ 617 617 \ 618 - memset (vs->tight.gradient.buffer, 0, w * 3 * sizeof(int)); \ 618 + memset(vs->tight->gradient.buffer, 0, w * 3 * sizeof(int)); \ 619 619 \ 620 620 endian = 0; /* FIXME */ \ 621 621 \ ··· 631 631 upper[c] = 0; \ 632 632 here[c] = 0; \ 633 633 } \ 634 - prev = (int *)vs->tight.gradient.buffer; \ 634 + prev = (int *)vs->tight->gradient.buffer; \ 635 635 for (x = 0; x < w; x++) { \ 636 636 pix = *buf; \ 637 637 if (endian) { \ ··· 785 785 static int tight_init_stream(VncState *vs, int stream_id, 786 786 int level, int strategy) 787 787 { 788 - z_streamp zstream = &vs->tight.stream[stream_id]; 788 + z_streamp zstream = &vs->tight->stream[stream_id]; 789 789 790 790 if (zstream->opaque == NULL) { 791 791 int err; ··· 803 803 return -1; 804 804 } 805 805 806 - vs->tight.levels[stream_id] = level; 806 + vs->tight->levels[stream_id] = level; 807 807 zstream->opaque = vs; 808 808 } 809 809 810 - if (vs->tight.levels[stream_id] != level) { 810 + if (vs->tight->levels[stream_id] != level) { 811 811 if (deflateParams(zstream, level, strategy) != Z_OK) { 812 812 return -1; 813 813 } 814 - vs->tight.levels[stream_id] = level; 814 + vs->tight->levels[stream_id] = level; 815 815 } 816 816 return 0; 817 817 } ··· 839 839 static int tight_compress_data(VncState *vs, int stream_id, size_t bytes, 840 840 int level, int strategy) 841 841 { 842 - z_streamp zstream = &vs->tight.stream[stream_id]; 842 + z_streamp zstream = &vs->tight->stream[stream_id]; 843 843 int previous_out; 844 844 845 845 if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) { 846 - vnc_write(vs, vs->tight.tight.buffer, vs->tight.tight.offset); 846 + vnc_write(vs, vs->tight->tight.buffer, vs->tight->tight.offset); 847 847 return bytes; 848 848 } 849 849 ··· 852 852 } 853 853 854 854 /* reserve memory in output buffer */ 855 - buffer_reserve(&vs->tight.zlib, bytes + 64); 855 + buffer_reserve(&vs->tight->zlib, bytes + 64); 856 856 857 857 /* set pointers */ 858 - zstream->next_in = vs->tight.tight.buffer; 859 - zstream->avail_in = vs->tight.tight.offset; 860 - zstream->next_out = vs->tight.zlib.buffer + vs->tight.zlib.offset; 861 - zstream->avail_out = vs->tight.zlib.capacity - vs->tight.zlib.offset; 858 + zstream->next_in = vs->tight->tight.buffer; 859 + zstream->avail_in = vs->tight->tight.offset; 860 + zstream->next_out = vs->tight->zlib.buffer + vs->tight->zlib.offset; 861 + zstream->avail_out = vs->tight->zlib.capacity - vs->tight->zlib.offset; 862 862 previous_out = zstream->avail_out; 863 863 zstream->data_type = Z_BINARY; 864 864 ··· 868 868 return -1; 869 869 } 870 870 871 - vs->tight.zlib.offset = vs->tight.zlib.capacity - zstream->avail_out; 871 + vs->tight->zlib.offset = vs->tight->zlib.capacity - zstream->avail_out; 872 872 /* ...how much data has actually been produced by deflate() */ 873 873 bytes = previous_out - zstream->avail_out; 874 874 875 875 tight_send_compact_size(vs, bytes); 876 - vnc_write(vs, vs->tight.zlib.buffer, bytes); 876 + vnc_write(vs, vs->tight->zlib.buffer, bytes); 877 877 878 - buffer_reset(&vs->tight.zlib); 878 + buffer_reset(&vs->tight->zlib); 879 879 880 880 return bytes; 881 881 } ··· 927 927 928 928 vnc_write_u8(vs, stream << 4); /* no flushing, no filter */ 929 929 930 - if (vs->tight.pixel24) { 931 - tight_pack24(vs, vs->tight.tight.buffer, w * h, &vs->tight.tight.offset); 930 + if (vs->tight->pixel24) { 931 + tight_pack24(vs, vs->tight->tight.buffer, w * h, 932 + &vs->tight->tight.offset); 932 933 bytes = 3; 933 934 } else { 934 935 bytes = vs->client_pf.bytes_per_pixel; 935 936 } 936 937 937 938 bytes = tight_compress_data(vs, stream, w * h * bytes, 938 - tight_conf[vs->tight.compression].raw_zlib_level, 939 - Z_DEFAULT_STRATEGY); 939 + tight_conf[vs->tight->compression].raw_zlib_level, 940 + Z_DEFAULT_STRATEGY); 940 941 941 942 return (bytes >= 0); 942 943 } ··· 947 948 948 949 vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */ 949 950 950 - if (vs->tight.pixel24) { 951 - tight_pack24(vs, vs->tight.tight.buffer, 1, &vs->tight.tight.offset); 951 + if (vs->tight->pixel24) { 952 + tight_pack24(vs, vs->tight->tight.buffer, 1, &vs->tight->tight.offset); 952 953 bytes = 3; 953 954 } else { 954 955 bytes = vs->client_pf.bytes_per_pixel; 955 956 } 956 957 957 - vnc_write(vs, vs->tight.tight.buffer, bytes); 958 + vnc_write(vs, vs->tight->tight.buffer, bytes); 958 959 return 1; 959 960 } 960 961 ··· 963 964 { 964 965 ssize_t bytes; 965 966 int stream = 1; 966 - int level = tight_conf[vs->tight.compression].mono_zlib_level; 967 + int level = tight_conf[vs->tight->compression].mono_zlib_level; 967 968 968 969 #ifdef CONFIG_VNC_PNG 969 970 if (tight_can_send_png_rect(vs, w, h)) { ··· 991 992 uint32_t buf[2] = {bg, fg}; 992 993 size_t ret = sizeof (buf); 993 994 994 - if (vs->tight.pixel24) { 995 + if (vs->tight->pixel24) { 995 996 tight_pack24(vs, (unsigned char*)buf, 2, &ret); 996 997 } 997 998 vnc_write(vs, buf, ret); 998 999 999 - tight_encode_mono_rect32(vs->tight.tight.buffer, w, h, bg, fg); 1000 + tight_encode_mono_rect32(vs->tight->tight.buffer, w, h, bg, fg); 1000 1001 break; 1001 1002 } 1002 1003 case 2: 1003 1004 vnc_write(vs, &bg, 2); 1004 1005 vnc_write(vs, &fg, 2); 1005 - tight_encode_mono_rect16(vs->tight.tight.buffer, w, h, bg, fg); 1006 + tight_encode_mono_rect16(vs->tight->tight.buffer, w, h, bg, fg); 1006 1007 break; 1007 1008 default: 1008 1009 vnc_write_u8(vs, bg); 1009 1010 vnc_write_u8(vs, fg); 1010 - tight_encode_mono_rect8(vs->tight.tight.buffer, w, h, bg, fg); 1011 + tight_encode_mono_rect8(vs->tight->tight.buffer, w, h, bg, fg); 1011 1012 break; 1012 1013 } 1013 - vs->tight.tight.offset = bytes; 1014 + vs->tight->tight.offset = bytes; 1014 1015 1015 1016 bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY); 1016 1017 return (bytes >= 0); ··· 1040 1041 static bool send_gradient_rect(VncState *vs, int x, int y, int w, int h) 1041 1042 { 1042 1043 int stream = 3; 1043 - int level = tight_conf[vs->tight.compression].gradient_zlib_level; 1044 + int level = tight_conf[vs->tight->compression].gradient_zlib_level; 1044 1045 ssize_t bytes; 1045 1046 1046 1047 if (vs->client_pf.bytes_per_pixel == 1) { ··· 1050 1051 vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4); 1051 1052 vnc_write_u8(vs, VNC_TIGHT_FILTER_GRADIENT); 1052 1053 1053 - buffer_reserve(&vs->tight.gradient, w * 3 * sizeof (int)); 1054 + buffer_reserve(&vs->tight->gradient, w * 3 * sizeof(int)); 1054 1055 1055 - if (vs->tight.pixel24) { 1056 - tight_filter_gradient24(vs, vs->tight.tight.buffer, w, h); 1056 + if (vs->tight->pixel24) { 1057 + tight_filter_gradient24(vs, vs->tight->tight.buffer, w, h); 1057 1058 bytes = 3; 1058 1059 } else if (vs->client_pf.bytes_per_pixel == 4) { 1059 - tight_filter_gradient32(vs, (uint32_t *)vs->tight.tight.buffer, w, h); 1060 + tight_filter_gradient32(vs, (uint32_t *)vs->tight->tight.buffer, w, h); 1060 1061 bytes = 4; 1061 1062 } else { 1062 - tight_filter_gradient16(vs, (uint16_t *)vs->tight.tight.buffer, w, h); 1063 + tight_filter_gradient16(vs, (uint16_t *)vs->tight->tight.buffer, w, h); 1063 1064 bytes = 2; 1064 1065 } 1065 1066 1066 - buffer_reset(&vs->tight.gradient); 1067 + buffer_reset(&vs->tight->gradient); 1067 1068 1068 1069 bytes = w * h * bytes; 1069 - vs->tight.tight.offset = bytes; 1070 + vs->tight->tight.offset = bytes; 1070 1071 1071 1072 bytes = tight_compress_data(vs, stream, bytes, 1072 1073 level, Z_FILTERED); ··· 1077 1078 int w, int h, VncPalette *palette) 1078 1079 { 1079 1080 int stream = 2; 1080 - int level = tight_conf[vs->tight.compression].idx_zlib_level; 1081 + int level = tight_conf[vs->tight->compression].idx_zlib_level; 1081 1082 int colors; 1082 1083 ssize_t bytes; 1083 1084 ··· 1104 1105 palette_iter(palette, write_palette, &priv); 1105 1106 vnc_write(vs, header, sizeof(header)); 1106 1107 1107 - if (vs->tight.pixel24) { 1108 + if (vs->tight->pixel24) { 1108 1109 tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset); 1109 1110 vs->output.offset = old_offset + offset; 1110 1111 } 1111 1112 1112 - tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); 1113 + tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, palette); 1113 1114 break; 1114 1115 } 1115 1116 case 2: ··· 1119 1120 1120 1121 palette_iter(palette, write_palette, &priv); 1121 1122 vnc_write(vs, header, sizeof(header)); 1122 - tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); 1123 + tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, palette); 1123 1124 break; 1124 1125 } 1125 1126 default: ··· 1127 1128 break; 1128 1129 } 1129 1130 bytes = w * h; 1130 - vs->tight.tight.offset = bytes; 1131 + vs->tight->tight.offset = bytes; 1131 1132 1132 1133 bytes = tight_compress_data(vs, stream, bytes, 1133 1134 level, Z_DEFAULT_STRATEGY); ··· 1146 1147 static void jpeg_init_destination(j_compress_ptr cinfo) 1147 1148 { 1148 1149 VncState *vs = cinfo->client_data; 1149 - Buffer *buffer = &vs->tight.jpeg; 1150 + Buffer *buffer = &vs->tight->jpeg; 1150 1151 1151 1152 cinfo->dest->next_output_byte = (JOCTET *)buffer->buffer + buffer->offset; 1152 1153 cinfo->dest->free_in_buffer = (size_t)(buffer->capacity - buffer->offset); ··· 1156 1157 static boolean jpeg_empty_output_buffer(j_compress_ptr cinfo) 1157 1158 { 1158 1159 VncState *vs = cinfo->client_data; 1159 - Buffer *buffer = &vs->tight.jpeg; 1160 + Buffer *buffer = &vs->tight->jpeg; 1160 1161 1161 1162 buffer->offset = buffer->capacity; 1162 1163 buffer_reserve(buffer, 2048); ··· 1168 1169 static void jpeg_term_destination(j_compress_ptr cinfo) 1169 1170 { 1170 1171 VncState *vs = cinfo->client_data; 1171 - Buffer *buffer = &vs->tight.jpeg; 1172 + Buffer *buffer = &vs->tight->jpeg; 1172 1173 1173 1174 buffer->offset = buffer->capacity - cinfo->dest->free_in_buffer; 1174 1175 } ··· 1187 1188 return send_full_color_rect(vs, x, y, w, h); 1188 1189 } 1189 1190 1190 - buffer_reserve(&vs->tight.jpeg, 2048); 1191 + buffer_reserve(&vs->tight->jpeg, 2048); 1191 1192 1192 1193 cinfo.err = jpeg_std_error(&jerr); 1193 1194 jpeg_create_compress(&cinfo); ··· 1222 1223 1223 1224 vnc_write_u8(vs, VNC_TIGHT_JPEG << 4); 1224 1225 1225 - tight_send_compact_size(vs, vs->tight.jpeg.offset); 1226 - vnc_write(vs, vs->tight.jpeg.buffer, vs->tight.jpeg.offset); 1227 - buffer_reset(&vs->tight.jpeg); 1226 + tight_send_compact_size(vs, vs->tight->jpeg.offset); 1227 + vnc_write(vs, vs->tight->jpeg.buffer, vs->tight->jpeg.offset); 1228 + buffer_reset(&vs->tight->jpeg); 1228 1229 1229 1230 return 1; 1230 1231 } ··· 1240 1241 VncState *vs = priv->vs; 1241 1242 png_colorp color = &priv->png_palette[idx]; 1242 1243 1243 - if (vs->tight.pixel24) 1244 + if (vs->tight->pixel24) 1244 1245 { 1245 1246 color->red = (pix >> vs->client_pf.rshift) & vs->client_pf.rmax; 1246 1247 color->green = (pix >> vs->client_pf.gshift) & vs->client_pf.gmax; ··· 1267 1268 { 1268 1269 VncState *vs = png_get_io_ptr(png_ptr); 1269 1270 1270 - buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); 1271 - memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); 1271 + buffer_reserve(&vs->tight->png, vs->tight->png.offset + length); 1272 + memcpy(vs->tight->png.buffer + vs->tight->png.offset, data, length); 1272 1273 1273 - vs->tight.png.offset += length; 1274 + vs->tight->png.offset += length; 1274 1275 } 1275 1276 1276 1277 static void png_flush_data(png_structp png_ptr) ··· 1295 1296 png_infop info_ptr; 1296 1297 png_colorp png_palette = NULL; 1297 1298 pixman_image_t *linebuf; 1298 - int level = tight_png_conf[vs->tight.compression].png_zlib_level; 1299 - int filters = tight_png_conf[vs->tight.compression].png_filters; 1299 + int level = tight_png_conf[vs->tight->compression].png_zlib_level; 1300 + int filters = tight_png_conf[vs->tight->compression].png_filters; 1300 1301 uint8_t *buf; 1301 1302 int dy; 1302 1303 ··· 1340 1341 png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); 1341 1342 1342 1343 if (vs->client_pf.bytes_per_pixel == 4) { 1343 - tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); 1344 + tight_encode_indexed_rect32(vs->tight->tight.buffer, w * h, 1345 + palette); 1344 1346 } else { 1345 - tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); 1347 + tight_encode_indexed_rect16(vs->tight->tight.buffer, w * h, 1348 + palette); 1346 1349 } 1347 1350 } 1348 1351 1349 1352 png_write_info(png_ptr, info_ptr); 1350 1353 1351 - buffer_reserve(&vs->tight.png, 2048); 1354 + buffer_reserve(&vs->tight->png, 2048); 1352 1355 linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, w); 1353 1356 buf = (uint8_t *)pixman_image_get_data(linebuf); 1354 1357 for (dy = 0; dy < h; dy++) 1355 1358 { 1356 1359 if (color_type == PNG_COLOR_TYPE_PALETTE) { 1357 - memcpy(buf, vs->tight.tight.buffer + (dy * w), w); 1360 + memcpy(buf, vs->tight->tight.buffer + (dy * w), w); 1358 1361 } else { 1359 1362 qemu_pixman_linebuf_fill(linebuf, vs->vd->server, w, x, y + dy); 1360 1363 } ··· 1372 1375 1373 1376 vnc_write_u8(vs, VNC_TIGHT_PNG << 4); 1374 1377 1375 - tight_send_compact_size(vs, vs->tight.png.offset); 1376 - vnc_write(vs, vs->tight.png.buffer, vs->tight.png.offset); 1377 - buffer_reset(&vs->tight.png); 1378 + tight_send_compact_size(vs, vs->tight->png.offset); 1379 + vnc_write(vs, vs->tight->png.buffer, vs->tight->png.offset); 1380 + buffer_reset(&vs->tight->png); 1378 1381 return 1; 1379 1382 } 1380 1383 #endif /* CONFIG_VNC_PNG */ 1381 1384 1382 1385 static void vnc_tight_start(VncState *vs) 1383 1386 { 1384 - buffer_reset(&vs->tight.tight); 1387 + buffer_reset(&vs->tight->tight); 1385 1388 1386 1389 // make the output buffer be the zlib buffer, so we can compress it later 1387 - vs->tight.tmp = vs->output; 1388 - vs->output = vs->tight.tight; 1390 + vs->tight->tmp = vs->output; 1391 + vs->output = vs->tight->tight; 1389 1392 } 1390 1393 1391 1394 static void vnc_tight_stop(VncState *vs) 1392 1395 { 1393 1396 // switch back to normal output/zlib buffers 1394 - vs->tight.tight = vs->output; 1395 - vs->output = vs->tight.tmp; 1397 + vs->tight->tight = vs->output; 1398 + vs->output = vs->tight->tmp; 1396 1399 } 1397 1400 1398 1401 static int send_sub_rect_nojpeg(VncState *vs, int x, int y, int w, int h, ··· 1426 1429 int ret; 1427 1430 1428 1431 if (colors == 0) { 1429 - if (force || (tight_jpeg_conf[vs->tight.quality].jpeg_full && 1432 + if (force || (tight_jpeg_conf[vs->tight->quality].jpeg_full && 1430 1433 tight_detect_smooth_image(vs, w, h))) { 1431 - int quality = tight_conf[vs->tight.quality].jpeg_quality; 1434 + int quality = tight_conf[vs->tight->quality].jpeg_quality; 1432 1435 1433 1436 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1434 1437 } else { ··· 1440 1443 ret = send_mono_rect(vs, x, y, w, h, bg, fg); 1441 1444 } else if (colors <= 256) { 1442 1445 if (force || (colors > 96 && 1443 - tight_jpeg_conf[vs->tight.quality].jpeg_idx && 1446 + tight_jpeg_conf[vs->tight->quality].jpeg_idx && 1444 1447 tight_detect_smooth_image(vs, w, h))) { 1445 - int quality = tight_conf[vs->tight.quality].jpeg_quality; 1448 + int quality = tight_conf[vs->tight->quality].jpeg_quality; 1446 1449 1447 1450 ret = send_jpeg_rect(vs, x, y, w, h, quality); 1448 1451 } else { ··· 1480 1483 qemu_thread_atexit_add(&vnc_tight_cleanup_notifier); 1481 1484 } 1482 1485 1483 - vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); 1486 + vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); 1484 1487 1485 1488 vnc_tight_start(vs); 1486 1489 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 1487 1490 vnc_tight_stop(vs); 1488 1491 1489 1492 #ifdef CONFIG_VNC_JPEG 1490 - if (!vs->vd->non_adaptive && vs->tight.quality != (uint8_t)-1) { 1493 + if (!vs->vd->non_adaptive && vs->tight->quality != (uint8_t)-1) { 1491 1494 double freq = vnc_update_freq(vs, x, y, w, h); 1492 1495 1493 - if (freq < tight_jpeg_conf[vs->tight.quality].jpeg_freq_min) { 1496 + if (freq < tight_jpeg_conf[vs->tight->quality].jpeg_freq_min) { 1494 1497 allow_jpeg = false; 1495 1498 } 1496 - if (freq >= tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { 1499 + if (freq >= tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { 1497 1500 force_jpeg = true; 1498 1501 vnc_sent_lossy_rect(vs, x, y, w, h); 1499 1502 } ··· 1503 1506 colors = tight_fill_palette(vs, x, y, w * h, &bg, &fg, color_count_palette); 1504 1507 1505 1508 #ifdef CONFIG_VNC_JPEG 1506 - if (allow_jpeg && vs->tight.quality != (uint8_t)-1) { 1509 + if (allow_jpeg && vs->tight->quality != (uint8_t)-1) { 1507 1510 ret = send_sub_rect_jpeg(vs, x, y, w, h, bg, fg, colors, 1508 1511 color_count_palette, force_jpeg); 1509 1512 } else { ··· 1520 1523 1521 1524 static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h) 1522 1525 { 1523 - vnc_framebuffer_update(vs, x, y, w, h, vs->tight.type); 1526 + vnc_framebuffer_update(vs, x, y, w, h, vs->tight->type); 1524 1527 1525 1528 vnc_tight_start(vs); 1526 1529 vnc_raw_send_framebuffer_update(vs, x, y, w, h); ··· 1538 1541 int rw, rh; 1539 1542 int n = 0; 1540 1543 1541 - max_size = tight_conf[vs->tight.compression].max_rect_size; 1542 - max_width = tight_conf[vs->tight.compression].max_rect_width; 1544 + max_size = tight_conf[vs->tight->compression].max_rect_size; 1545 + max_width = tight_conf[vs->tight->compression].max_rect_width; 1543 1546 1544 1547 if (split && (w > max_width || w * h > max_size)) { 1545 1548 max_sub_width = (w > max_width) ? max_width : w; ··· 1648 1651 1649 1652 if (vs->client_pf.bytes_per_pixel == 4 && vs->client_pf.rmax == 0xFF && 1650 1653 vs->client_pf.bmax == 0xFF && vs->client_pf.gmax == 0xFF) { 1651 - vs->tight.pixel24 = true; 1654 + vs->tight->pixel24 = true; 1652 1655 } else { 1653 - vs->tight.pixel24 = false; 1656 + vs->tight->pixel24 = false; 1654 1657 } 1655 1658 1656 1659 #ifdef CONFIG_VNC_JPEG 1657 - if (vs->tight.quality != (uint8_t)-1) { 1660 + if (vs->tight->quality != (uint8_t)-1) { 1658 1661 double freq = vnc_update_freq(vs, x, y, w, h); 1659 1662 1660 - if (freq > tight_jpeg_conf[vs->tight.quality].jpeg_freq_threshold) { 1663 + if (freq > tight_jpeg_conf[vs->tight->quality].jpeg_freq_threshold) { 1661 1664 return send_rect_simple(vs, x, y, w, h, false); 1662 1665 } 1663 1666 } ··· 1669 1672 1670 1673 /* Calculate maximum number of rows in one non-solid rectangle. */ 1671 1674 1672 - max_rows = tight_conf[vs->tight.compression].max_rect_size; 1673 - max_rows /= MIN(tight_conf[vs->tight.compression].max_rect_width, w); 1675 + max_rows = tight_conf[vs->tight->compression].max_rect_size; 1676 + max_rows /= MIN(tight_conf[vs->tight->compression].max_rect_width, w); 1674 1677 1675 1678 return find_large_solid_color_rect(vs, x, y, w, h, max_rows); 1676 1679 } ··· 1678 1681 int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, 1679 1682 int w, int h) 1680 1683 { 1681 - vs->tight.type = VNC_ENCODING_TIGHT; 1684 + vs->tight->type = VNC_ENCODING_TIGHT; 1682 1685 return tight_send_framebuffer_update(vs, x, y, w, h); 1683 1686 } 1684 1687 1685 1688 int vnc_tight_png_send_framebuffer_update(VncState *vs, int x, int y, 1686 1689 int w, int h) 1687 1690 { 1688 - vs->tight.type = VNC_ENCODING_TIGHT_PNG; 1691 + vs->tight->type = VNC_ENCODING_TIGHT_PNG; 1689 1692 return tight_send_framebuffer_update(vs, x, y, w, h); 1690 1693 } 1691 1694 1692 1695 void vnc_tight_clear(VncState *vs) 1693 1696 { 1694 1697 int i; 1695 - for (i=0; i<ARRAY_SIZE(vs->tight.stream); i++) { 1696 - if (vs->tight.stream[i].opaque) { 1697 - deflateEnd(&vs->tight.stream[i]); 1698 + for (i = 0; i < ARRAY_SIZE(vs->tight->stream); i++) { 1699 + if (vs->tight->stream[i].opaque) { 1700 + deflateEnd(&vs->tight->stream[i]); 1698 1701 } 1699 1702 } 1700 1703 1701 - buffer_free(&vs->tight.tight); 1702 - buffer_free(&vs->tight.zlib); 1703 - buffer_free(&vs->tight.gradient); 1704 + buffer_free(&vs->tight->tight); 1705 + buffer_free(&vs->tight->zlib); 1706 + buffer_free(&vs->tight->gradient); 1704 1707 #ifdef CONFIG_VNC_JPEG 1705 - buffer_free(&vs->tight.jpeg); 1708 + buffer_free(&vs->tight->jpeg); 1706 1709 #endif 1707 1710 #ifdef CONFIG_VNC_PNG 1708 - buffer_free(&vs->tight.png); 1711 + buffer_free(&vs->tight->png); 1709 1712 #endif 1710 1713 }
+6 -5
ui/vnc-enc-zlib.c
··· 76 76 zstream->zalloc = vnc_zlib_zalloc; 77 77 zstream->zfree = vnc_zlib_zfree; 78 78 79 - err = deflateInit2(zstream, vs->tight.compression, Z_DEFLATED, MAX_WBITS, 79 + err = deflateInit2(zstream, vs->tight->compression, Z_DEFLATED, 80 + MAX_WBITS, 80 81 MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); 81 82 82 83 if (err != Z_OK) { ··· 84 85 return -1; 85 86 } 86 87 87 - vs->zlib.level = vs->tight.compression; 88 + vs->zlib.level = vs->tight->compression; 88 89 zstream->opaque = vs; 89 90 } 90 91 91 - if (vs->tight.compression != vs->zlib.level) { 92 - if (deflateParams(zstream, vs->tight.compression, 92 + if (vs->tight->compression != vs->zlib.level) { 93 + if (deflateParams(zstream, vs->tight->compression, 93 94 Z_DEFAULT_STRATEGY) != Z_OK) { 94 95 return -1; 95 96 } 96 - vs->zlib.level = vs->tight.compression; 97 + vs->zlib.level = vs->tight->compression; 97 98 } 98 99 99 100 // reserve memory in output buffer
+34 -34
ui/vnc-enc-zrle.c
··· 37 37 38 38 static void vnc_zrle_start(VncState *vs) 39 39 { 40 - buffer_reset(&vs->zrle.zrle); 40 + buffer_reset(&vs->zrle->zrle); 41 41 42 42 /* make the output buffer be the zlib buffer, so we can compress it later */ 43 - vs->zrle.tmp = vs->output; 44 - vs->output = vs->zrle.zrle; 43 + vs->zrle->tmp = vs->output; 44 + vs->output = vs->zrle->zrle; 45 45 } 46 46 47 47 static void vnc_zrle_stop(VncState *vs) 48 48 { 49 49 /* switch back to normal output/zlib buffers */ 50 - vs->zrle.zrle = vs->output; 51 - vs->output = vs->zrle.tmp; 50 + vs->zrle->zrle = vs->output; 51 + vs->output = vs->zrle->tmp; 52 52 } 53 53 54 54 static void *zrle_convert_fb(VncState *vs, int x, int y, int w, int h, ··· 56 56 { 57 57 Buffer tmp; 58 58 59 - buffer_reset(&vs->zrle.fb); 60 - buffer_reserve(&vs->zrle.fb, w * h * bpp + bpp); 59 + buffer_reset(&vs->zrle->fb); 60 + buffer_reserve(&vs->zrle->fb, w * h * bpp + bpp); 61 61 62 62 tmp = vs->output; 63 - vs->output = vs->zrle.fb; 63 + vs->output = vs->zrle->fb; 64 64 65 65 vnc_raw_send_framebuffer_update(vs, x, y, w, h); 66 66 67 - vs->zrle.fb = vs->output; 67 + vs->zrle->fb = vs->output; 68 68 vs->output = tmp; 69 - return vs->zrle.fb.buffer; 69 + return vs->zrle->fb.buffer; 70 70 } 71 71 72 72 static int zrle_compress_data(VncState *vs, int level) 73 73 { 74 - z_streamp zstream = &vs->zrle.stream; 74 + z_streamp zstream = &vs->zrle->stream; 75 75 76 - buffer_reset(&vs->zrle.zlib); 76 + buffer_reset(&vs->zrle->zlib); 77 77 78 78 if (zstream->opaque != vs) { 79 79 int err; ··· 93 93 } 94 94 95 95 /* reserve memory in output buffer */ 96 - buffer_reserve(&vs->zrle.zlib, vs->zrle.zrle.offset + 64); 96 + buffer_reserve(&vs->zrle->zlib, vs->zrle->zrle.offset + 64); 97 97 98 98 /* set pointers */ 99 - zstream->next_in = vs->zrle.zrle.buffer; 100 - zstream->avail_in = vs->zrle.zrle.offset; 101 - zstream->next_out = vs->zrle.zlib.buffer + vs->zrle.zlib.offset; 102 - zstream->avail_out = vs->zrle.zlib.capacity - vs->zrle.zlib.offset; 99 + zstream->next_in = vs->zrle->zrle.buffer; 100 + zstream->avail_in = vs->zrle->zrle.offset; 101 + zstream->next_out = vs->zrle->zlib.buffer + vs->zrle->zlib.offset; 102 + zstream->avail_out = vs->zrle->zlib.capacity - vs->zrle->zlib.offset; 103 103 zstream->data_type = Z_BINARY; 104 104 105 105 /* start encoding */ ··· 108 108 return -1; 109 109 } 110 110 111 - vs->zrle.zlib.offset = vs->zrle.zlib.capacity - zstream->avail_out; 112 - return vs->zrle.zlib.offset; 111 + vs->zrle->zlib.offset = vs->zrle->zlib.capacity - zstream->avail_out; 112 + return vs->zrle->zlib.offset; 113 113 } 114 114 115 115 /* Try to work out whether to use RLE and/or a palette. We do this by ··· 259 259 size_t bytes; 260 260 int zywrle_level; 261 261 262 - if (vs->zrle.type == VNC_ENCODING_ZYWRLE) { 263 - if (!vs->vd->lossy || vs->tight.quality == (uint8_t)-1 264 - || vs->tight.quality == 9) { 262 + if (vs->zrle->type == VNC_ENCODING_ZYWRLE) { 263 + if (!vs->vd->lossy || vs->tight->quality == (uint8_t)-1 264 + || vs->tight->quality == 9) { 265 265 zywrle_level = 0; 266 - vs->zrle.type = VNC_ENCODING_ZRLE; 267 - } else if (vs->tight.quality < 3) { 266 + vs->zrle->type = VNC_ENCODING_ZRLE; 267 + } else if (vs->tight->quality < 3) { 268 268 zywrle_level = 3; 269 - } else if (vs->tight.quality < 6) { 269 + } else if (vs->tight->quality < 6) { 270 270 zywrle_level = 2; 271 271 } else { 272 272 zywrle_level = 1; ··· 337 337 338 338 vnc_zrle_stop(vs); 339 339 bytes = zrle_compress_data(vs, Z_DEFAULT_COMPRESSION); 340 - vnc_framebuffer_update(vs, x, y, w, h, vs->zrle.type); 340 + vnc_framebuffer_update(vs, x, y, w, h, vs->zrle->type); 341 341 vnc_write_u32(vs, bytes); 342 - vnc_write(vs, vs->zrle.zlib.buffer, vs->zrle.zlib.offset); 342 + vnc_write(vs, vs->zrle->zlib.buffer, vs->zrle->zlib.offset); 343 343 return 1; 344 344 } 345 345 346 346 int vnc_zrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 347 347 { 348 - vs->zrle.type = VNC_ENCODING_ZRLE; 348 + vs->zrle->type = VNC_ENCODING_ZRLE; 349 349 return zrle_send_framebuffer_update(vs, x, y, w, h); 350 350 } 351 351 352 352 int vnc_zywrle_send_framebuffer_update(VncState *vs, int x, int y, int w, int h) 353 353 { 354 - vs->zrle.type = VNC_ENCODING_ZYWRLE; 354 + vs->zrle->type = VNC_ENCODING_ZYWRLE; 355 355 return zrle_send_framebuffer_update(vs, x, y, w, h); 356 356 } 357 357 358 358 void vnc_zrle_clear(VncState *vs) 359 359 { 360 - if (vs->zrle.stream.opaque) { 361 - deflateEnd(&vs->zrle.stream); 360 + if (vs->zrle->stream.opaque) { 361 + deflateEnd(&vs->zrle->stream); 362 362 } 363 - buffer_free(&vs->zrle.zrle); 364 - buffer_free(&vs->zrle.fb); 365 - buffer_free(&vs->zrle.zlib); 363 + buffer_free(&vs->zrle->zrle); 364 + buffer_free(&vs->zrle->fb); 365 + buffer_free(&vs->zrle->zlib); 366 366 }
+1 -1
ui/vnc-enc-zrle.inc.c
··· 96 96 static void ZRLE_ENCODE_TILE(VncState *vs, ZRLE_PIXEL *data, int w, int h, 97 97 int zywrle_level) 98 98 { 99 - VncPalette *palette = &vs->zrle.palette; 99 + VncPalette *palette = &vs->zrle->palette; 100 100 101 101 int runs = 0; 102 102 int single_pixels = 0;
+16 -12
ui/vnc.c
··· 1307 1307 object_unref(OBJECT(vs->sioc)); 1308 1308 vs->sioc = NULL; 1309 1309 vs->magic = 0; 1310 + g_free(vs->zrle); 1311 + g_free(vs->tight); 1310 1312 g_free(vs); 1311 1313 } 1312 1314 ··· 2058 2060 2059 2061 vs->features = 0; 2060 2062 vs->vnc_encoding = 0; 2061 - vs->tight.compression = 9; 2062 - vs->tight.quality = -1; /* Lossless by default */ 2063 + vs->tight->compression = 9; 2064 + vs->tight->quality = -1; /* Lossless by default */ 2063 2065 vs->absolute = -1; 2064 2066 2065 2067 /* ··· 2127 2129 vs->features |= VNC_FEATURE_LED_STATE_MASK; 2128 2130 break; 2129 2131 case VNC_ENCODING_COMPRESSLEVEL0 ... VNC_ENCODING_COMPRESSLEVEL0 + 9: 2130 - vs->tight.compression = (enc & 0x0F); 2132 + vs->tight->compression = (enc & 0x0F); 2131 2133 break; 2132 2134 case VNC_ENCODING_QUALITYLEVEL0 ... VNC_ENCODING_QUALITYLEVEL0 + 9: 2133 2135 if (vs->vd->lossy) { 2134 - vs->tight.quality = (enc & 0x0F); 2136 + vs->tight->quality = (enc & 0x0F); 2135 2137 } 2136 2138 break; 2137 2139 default: ··· 3034 3036 int i; 3035 3037 3036 3038 trace_vnc_client_connect(vs, sioc); 3039 + vs->zrle = g_new0(VncZrle, 1); 3040 + vs->tight = g_new0(VncTight, 1); 3037 3041 vs->magic = VNC_MAGIC; 3038 3042 vs->sioc = sioc; 3039 3043 object_ref(OBJECT(vs->sioc)); ··· 3045 3049 buffer_init(&vs->output, "vnc-output/%p", sioc); 3046 3050 buffer_init(&vs->jobs_buffer, "vnc-jobs_buffer/%p", sioc); 3047 3051 3048 - buffer_init(&vs->tight.tight, "vnc-tight/%p", sioc); 3049 - buffer_init(&vs->tight.zlib, "vnc-tight-zlib/%p", sioc); 3050 - buffer_init(&vs->tight.gradient, "vnc-tight-gradient/%p", sioc); 3052 + buffer_init(&vs->tight->tight, "vnc-tight/%p", sioc); 3053 + buffer_init(&vs->tight->zlib, "vnc-tight-zlib/%p", sioc); 3054 + buffer_init(&vs->tight->gradient, "vnc-tight-gradient/%p", sioc); 3051 3055 #ifdef CONFIG_VNC_JPEG 3052 - buffer_init(&vs->tight.jpeg, "vnc-tight-jpeg/%p", sioc); 3056 + buffer_init(&vs->tight->jpeg, "vnc-tight-jpeg/%p", sioc); 3053 3057 #endif 3054 3058 #ifdef CONFIG_VNC_PNG 3055 - buffer_init(&vs->tight.png, "vnc-tight-png/%p", sioc); 3059 + buffer_init(&vs->tight->png, "vnc-tight-png/%p", sioc); 3056 3060 #endif 3057 3061 buffer_init(&vs->zlib.zlib, "vnc-zlib/%p", sioc); 3058 - buffer_init(&vs->zrle.zrle, "vnc-zrle/%p", sioc); 3059 - buffer_init(&vs->zrle.fb, "vnc-zrle-fb/%p", sioc); 3060 - buffer_init(&vs->zrle.zlib, "vnc-zrle-zlib/%p", sioc); 3062 + buffer_init(&vs->zrle->zrle, "vnc-zrle/%p", sioc); 3063 + buffer_init(&vs->zrle->fb, "vnc-zrle-fb/%p", sioc); 3064 + buffer_init(&vs->zrle->zlib, "vnc-zrle-zlib/%p", sioc); 3061 3065 3062 3066 if (skipauth) { 3063 3067 vs->auth = VNC_AUTH_NONE;
+2 -2
ui/vnc.h
··· 338 338 /* Encoding specific, if you add something here, don't forget to 339 339 * update vnc_async_encoding_start() 340 340 */ 341 - VncTight tight; 341 + VncTight *tight; 342 342 VncZlib zlib; 343 343 VncHextile hextile; 344 - VncZrle zrle; 344 + VncZrle *zrle; 345 345 VncZywrle zywrle; 346 346 347 347 Notifier mouse_mode_notifier;