Skip to content

fix(client): Clear internal client buffer on failed packet send#9100

Open
TreeHunter9 wants to merge 1 commit into
FirebirdSQL:masterfrom
TreeHunter9:master_cleanup_on_failed_send_packet
Open

fix(client): Clear internal client buffer on failed packet send#9100
TreeHunter9 wants to merge 1 commit into
FirebirdSQL:masterfrom
TreeHunter9:master_cleanup_on_failed_send_packet

Conversation

@TreeHunter9

Copy link
Copy Markdown
Contributor

Previously a failed send left stale bytes in the buffer, which got prepended to the next packet.

Previously a failed send left stale bytes in the buffer, which got prepended to the next packet.
@TreeHunter9

Copy link
Copy Markdown
Contributor Author

The incorrect behavior can be seeing in this example:

#include "ibase.h"
#include <stdio.h>
#include <string.h>

static void print_status_vector(const ISC_STATUS *status_vector) {
	char buffer[512] = {};
	while (fb_interpret(buffer, 512, &status_vector))
		printf("%s\n", buffer);
}

int main(int argc, char **argv) {
	const char *db  = "localhost:employee", 
			   *usr = "sysdba",
			   *pwd = "masterkey";

	ISC_STATUS_ARRAY st = {0};
	isc_db_handle dbh = 0;
	isc_tr_handle tr = 0;
	char dpb[256]; int dl = 0;
	dpb[dl++] = isc_dpb_version1;
	dpb[dl++] = isc_dpb_user_name;
	dpb[dl++] = (char)strlen(usr);
	memcpy(dpb + dl, usr, strlen(usr));
	dl += strlen(usr);
	dpb[dl++] = isc_dpb_password;
	dpb[dl++] = (char)strlen(pwd);
	memcpy(dpb + dl, pwd, strlen(pwd));
	dl += strlen(pwd);

	if (isc_attach_database(st, strlen(db), (char *)db, &dbh, dl, dpb)) {
		print_status_vector(st);
		return 1;
	}
	if (isc_start_transaction(st, &tr, 1, &dbh, 0, NULL)) {
		print_status_vector(st);
		return 1;
	}

	ISC_ARRAY_DESC desc;
	desc.array_desc_dtype = 8;
	desc.array_desc_scale = 0;
	desc.array_desc_length = 4;
	memcpy(desc.array_desc_field_name, "A", 1);
	memcpy(desc.array_desc_relation_name, "ARR", 3);
	desc.array_desc_dimensions = 1;
	desc.array_desc_flags = 0;
	desc.array_desc_bounds[0].array_bound_lower = 1;
	desc.array_desc_bounds[0].array_bound_upper = 3;

	ISC_QUAD aid = {0, 1};

	unsigned char sdl[64]; int n = 0;
	sdl[n++] = 2;

	char slice[256] = {0}; ISC_LONG slen = 0;
	// Will throw an error in the client lib, packet will not be send, but it is stored in buffer.
	isc_get_slice(st, &dbh, &tr, &aid, (unsigned short)n, (const ISC_UCHAR *)sdl,
				0, NULL, (ISC_LONG)sizeof(slice), slice, &slen);
	print_status_vector(st);

	// Will send two packets, incomplete `isc_get_slice` and `isc_commit_transaction`.
	// The client will get an error and will think that it is from `isc_commit_transaction`, but it actually from `isc_get_slice` API call.
	isc_commit_transaction(st, &tr);
	print_status_vector(st);
	isc_detach_database(st, &dbh);
	print_status_vector(st);
	return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant