PER encoding fix. Reported by Grzegorz Aksamit.
diff --git a/ChangeLog b/ChangeLog
index 58b381c..3c964b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,12 @@
 
-0.9.23:	2010-Oct-07
+0.9.23:	2010-Oct-24
 
 	* GeneralizedTime fix for working with time offsets which are not
 	  representable in whole hours. (Severity: low; Security impact: low)
 	  Thanks to IP Fabrics, Inc.
 	* Added -fincludes-quoted to asn1c to generate #includes in "double"
 	  instead of <angle> quotes.
+	* PER encoding correctness fix. Reported by Grzegorz Aksamit.
 
 0.9.22:	2008-Nov-19
 
diff --git a/skeletons/per_support.c b/skeletons/per_support.c
index e8299c7..658da95 100644
--- a/skeletons/per_support.c
+++ b/skeletons/per_support.c
@@ -307,7 +307,7 @@
 	 */
 	buf = po->buffer;
 	omsk = ~((1 << (8 - po->nboff)) - 1);
-	off = (po->nboff += obits);
+	off = (po->nboff + obits);
 
 	/* Clear data of debris before meaningful bits */
 	bits &= (((uint32_t)1 << obits) - 1);
@@ -317,18 +317,22 @@
 		po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk);
 
 	if(off <= 8)	/* Completely within 1 byte */
+		po->nboff = off,
 		bits <<= (8 - off),
 		buf[0] = (buf[0] & omsk) | bits;
 	else if(off <= 16)
+		po->nboff = off,
 		bits <<= (16 - off),
 		buf[0] = (buf[0] & omsk) | (bits >> 8),
 		buf[1] = bits;
 	else if(off <= 24)
+		po->nboff = off,
 		bits <<= (24 - off),
 		buf[0] = (buf[0] & omsk) | (bits >> 16),
 		buf[1] = bits >> 8,
 		buf[2] = bits;
 	else if(off <= 31)
+		po->nboff = off,
 		bits <<= (32 - off),
 		buf[0] = (buf[0] & omsk) | (bits >> 24),
 		buf[1] = bits >> 16,
@@ -336,7 +340,7 @@
 		buf[3] = bits;
 	else {
 		ASN_DEBUG("->[PER out split %d]", obits);
-		per_put_few_bits(po, bits >> 8, 24);
+		per_put_few_bits(po, bits >> (obits - 24), 24);
 		per_put_few_bits(po, bits, obits - 24);
 		ASN_DEBUG("<-[PER out split %d]", obits);
 	}
diff --git a/skeletons/tests/check-PER.c b/skeletons/tests/check-PER.c
index 12e700c..32ac52a 100644
--- a/skeletons/tests/check-PER.c
+++ b/skeletons/tests/check-PER.c
@@ -213,12 +213,82 @@
 	assert(po.tmpspace[5] == 0xff);
 	assert(po.tmpspace[6] == 0xfe);
 
+}
 
+static void
+check_per_encoding_sweep_with(uint8_t buf[], int already_bits, int add_bits) {
+	size_t buf_size = 8;
+	asn_per_data_t pos;
+	asn_per_outp_t out;
+	int32_t d_already;
+	int32_t d_add;
+	int32_t d_left;
+	int left_bits;
+	int i;
+
+	memset(&pos, 0, sizeof(pos));
+	pos.buffer = buf;
+	pos.nboff = 0;
+	pos.nbits = buf_size * 8;
+
+	memset(&out, 0, sizeof(out));
+	out.buffer = out.tmpspace;
+	out.nbits = 8 * sizeof(out.tmpspace);
+	assert(sizeof(out.tmpspace) >= buf_size);
+	memcpy(out.buffer, buf, buf_size);
+
+	d_already = per_get_few_bits(&pos, already_bits);
+	d_add = per_get_few_bits(&pos, add_bits);
+
+	per_put_few_bits(&out, d_already, already_bits);
+	per_put_few_bits(&out, d_add, add_bits);
+	if(out.nboff % 8) {
+		left_bits = 8 - (out.nboff % 8);
+		d_left = per_get_few_bits(&pos, left_bits);
+	} else {
+		left_bits = 0;
+		d_left = 0;
+	}
+	per_put_few_bits(&out, d_left, left_bits);
+	assert(0 == (out.nboff % 8));
+
+	if(0 != memcmp(out.tmpspace, buf, buf_size)) {
+		printf("IN: ");
+		for(i = 0; i < buf_size; i++)
+			printf(" %02x", buf[i]);
+		printf("\nOUT:");
+		for(i = 0; i < buf_size; i++)
+			printf(" %02x", out.tmpspace[i]);
+		printf(" (out{nboff=%d,left=%d,%02x})\n", (int)out.nboff, left_bits, (int)d_left);
+		assert(0 == memcmp(out.tmpspace, buf, buf_size));
+	}
+}
+
+static void
+check_per_encoding_sweep() {
+	uint8_t buf[3][8] = {
+		{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA },
+		{ 0xB7, 0x19, 0x2F, 0xEE, 0xAD, 0x11, 0xAA, 0x55 },
+		{ 0xEE, 0xAD, 0x11, 0xAA, 0x55, 0xB7, 0x19, 0x2F }
+	};
+	int already_bits;
+	int add_bits;
+	int buf_idx;
+
+	for(buf_idx = 0; buf_idx < 3; buf_idx++) {
+	 for(already_bits = 0; already_bits < 24; already_bits++) {
+	  for(add_bits = 0; add_bits <= 31; add_bits++) {
+	   /*fprintf(stderr, "PER %d += %d\n", already_bits, add_bits);*/
+	   check_per_encoding_sweep_with(buf[buf_idx], already_bits, add_bits);
+	  }
+	 }
+	}
 }
 
 int
 main() {
 	check_per_decoding();
 	check_per_encoding();
+	check_per_encoding_sweep();
 	return 0;
 }