diff --git a/src/protocols/rdp/channels/cliprdr.c b/src/protocols/rdp/channels/cliprdr.c index bc9366638..39a921c1b 100644 --- a/src/protocols/rdp/channels/cliprdr.c +++ b/src/protocols/rdp/channels/cliprdr.c @@ -403,8 +403,19 @@ static UINT guac_rdp_cliprdr_format_data_request(CliprdrClientContext* cliprdr, * requested */ BYTE* start = (BYTE*) output; guac_iconv_read* local_reader = settings->normalize_clipboard ? GUAC_READ_UTF8_NORMALIZED : GUAC_READ_UTF8; - guac_iconv(local_reader, &input, clipboard->clipboard->length, - remote_writer, &output, output_buf_size); + + /* A zero return indicates the output buffer filled before all input was + * consumed (truncation). Charset expansion (UTF-8 -> UTF-16, CRLF + * translation, or multi-byte characters such as emoji) can outgrow the + * configured clipboard buffer, so warn the operator rather than silently + * sending truncated data. */ + if (!guac_iconv(local_reader, &input, clipboard->clipboard->length, + remote_writer, &output, output_buf_size)) { + guac_client_log(client, GUAC_LOG_WARNING, "CLIPRDR: Outbound clipboard " + "data was truncated to fit the %d-byte clipboard buffer. " + "Increase \"clipboard-buffer-size\" to transfer larger " + "clipboard content.", output_buf_size); + } CLIPRDR_FORMAT_DATA_RESPONSE data_response = { .requestedFormatData = (BYTE*) start, @@ -513,11 +524,17 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, data_len = format_data_response->dataLen; #endif - /* Convert, store, and forward the clipboard data received from RDP - * server */ - if (guac_iconv(remote_reader, &input, data_len, - GUAC_WRITE_UTF8, &output, output_buf_size)) { - int length = strnlen(received_data, output_buf_size); + /* Convert the clipboard data received from the RDP server. A zero return + * indicates the output buffer filled before all input was consumed + * (truncation) due to charset expansion. */ + int converted = guac_iconv(remote_reader, &input, data_len, + GUAC_WRITE_UTF8, &output, output_buf_size); + + /* Store and forward whatever was converted, even if truncated. Partial + * clipboard text is still useful, so we deliver it and warn the operator + * rather than dropping the paste entirely. */ + int length = strnlen(received_data, output_buf_size); + if (length > 0) { guac_common_clipboard_reset(clipboard->clipboard, "text/plain"); guac_common_clipboard_append(clipboard->clipboard, received_data, length); guac_common_clipboard_send(clipboard->clipboard, client); @@ -530,6 +547,13 @@ static UINT guac_rdp_cliprdr_format_data_response(CliprdrClientContext* cliprdr, clipboard->clipboard->length); } + if (!converted) { + guac_client_log(client, GUAC_LOG_WARNING, "CLIPRDR: Inbound clipboard " + "data was truncated to fit the %d-byte clipboard buffer. " + "Increase \"clipboard-buffer-size\" to receive larger " + "clipboard content.", output_buf_size); + } + guac_mem_free(received_data); return CHANNEL_RC_OK; diff --git a/src/protocols/vnc/clipboard.c b/src/protocols/vnc/clipboard.c index 2a30d5d26..0fd45f5cd 100644 --- a/src/protocols/vnc/clipboard.c +++ b/src/protocols/vnc/clipboard.c @@ -191,9 +191,16 @@ int guac_vnc_clipboard_end_handler(guac_user* user, guac_stream* stream) { char* output = output_data; guac_iconv_write* writer = vnc_client->clipboard_writer; - /* Convert clipboard contents */ - guac_iconv(GUAC_READ_UTF8, &input, clipboard->length, - writer, &output, output_buf_size); + /* Convert clipboard contents. A zero return indicates the output buffer + * filled before all input was consumed (truncation) due to charset + * expansion; warn rather than silently sending truncated data. */ + if (!guac_iconv(GUAC_READ_UTF8, &input, clipboard->length, + writer, &output, output_buf_size)) { + guac_client_log(client, GUAC_LOG_WARNING, "VNC: Outbound clipboard " + "data was truncated to fit the %d-byte clipboard buffer. " + "Increase \"clipboard-buffer-size\" to transfer larger " + "clipboard content.", output_buf_size); + } SendClientCutText(rfb_client, output_data, output - output_data); @@ -224,9 +231,16 @@ void guac_vnc_cut_text(rfbClient* client, const char* text, int textlen) { char* output = received_data; guac_iconv_read* reader = vnc_client->clipboard_reader; - /* Convert clipboard contents */ - guac_iconv(reader, &input, textlen, - GUAC_WRITE_UTF8, &output, output_buf_size); + /* Convert clipboard contents. A zero return indicates the output buffer + * filled before all input was consumed (truncation) due to charset + * expansion; warn rather than silently delivering truncated data. */ + if (!guac_iconv(reader, &input, textlen, + GUAC_WRITE_UTF8, &output, output_buf_size)) { + guac_client_log(gc, GUAC_LOG_WARNING, "VNC: Inbound clipboard data " + "was truncated to fit the %d-byte clipboard buffer. Increase " + "\"clipboard-buffer-size\" to receive larger clipboard " + "content.", output_buf_size); + } /* Send converted data */ guac_common_clipboard_reset(vnc_client->clipboard, "text/plain");