static int charstring_make_notdef(gs_glyph_data_t *pgd, gs_font *font) { gs_font_type1 *const pfont = (gs_font_type1 *)font; static const byte char_data[4] = { 139, /* 0 */ 139, /* 0 */ c1_hsbw, cx_endchar }; uint len = max(pfont->data.lenIV, 0) + sizeof(char_data); byte *chars = gs_alloc_string(font->memory, len, "charstring_make_notdef"); if (chars == 0) return_error(e_VMerror); gs_glyph_data_from_string(pgd, chars, len, font); if (pfont->data.lenIV < 0) memcpy(chars, char_data, sizeof(char_data)); else { crypt_state state = crypt_charstring_seed; memcpy(chars + pfont->data.lenIV, char_data, sizeof(char_data)); gs_type1_encrypt(chars, chars, len, &state); } return 0; }
/* Encrypt and write a CharString. */ static int stream_write_encrypted(stream *s, const void *ptr, uint count) { const byte *const data = ptr; crypt_state state = crypt_charstring_seed; byte buf[50]; /* arbitrary */ uint left, n; int code = 0; for (left = count; left > 0; left -= n) { n = min(left, sizeof(buf)); gs_type1_encrypt(buf, data + count - left, n, &state); code = stream_write(s, buf, n); } return code; }
/* Process a buffer */ static int s_exE_process(stream_state * st, stream_cursor_read * pr, stream_cursor_write * pw, bool last) { stream_exE_state *const ss = (stream_exE_state *) st; const byte *p = pr->ptr; byte *q = pw->ptr; uint rcount = pr->limit - p; uint wcount = pw->limit - q; uint count; int status; if (rcount <= wcount) count = rcount, status = 0; else count = wcount, status = 1; gs_type1_encrypt(q + 1, p + 1, count, (crypt_state *)&ss->cstate); pr->ptr += count; pw->ptr += count; return status; }
static int strip_othersubrs(gs_glyph_data_t *gdata, gs_font_type1 *pfont, byte *stripped, byte *SubrsWithMM) { crypt_state state = crypt_charstring_seed; gs_bytestring *data = (gs_bytestring *)&gdata->bits; byte *source = data->data, *dest = stripped, *end = source + data->size; int i, dest_length = 0, CurrentNumberIndex = 0, Stack[64], written; int OnlyCalcLength = 0; char Buffer[16]; memset(Stack, 0x00, 64 * sizeof(int)); if (stripped == NULL) { OnlyCalcLength = 1; dest = (byte *)&Buffer; } gs_type1_decrypt(source, source, data->size, &state); if(pfont->data.lenIV >= 0) { for (i=0;i<pfont->data.lenIV;i++) { if (!OnlyCalcLength) *dest++ = *source++; } dest_length += pfont->data.lenIV; } while (source < end) { if (*source < 32) { /* Command */ switch (*source) { case 12: if (*(source + 1) == 16) { /* Callothersubsr, the only thing we care about */ switch(Stack[CurrentNumberIndex-1]) { /* If we find a Multiple Master call, remove all but the * first set of arguments. Mimics the result of a call. * Adobe 'encourages' the use of Subrs to do MM, but * the spec doens't say you have to, so we need to be * prepared, just in case. I doubt we will ever execute * this code. */ case 14: CurrentNumberIndex -= pfont->data.WeightVector.count - 1; for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source += 2; break; case 15: CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 2; for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source += 2; break; case 16: CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 3; for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source += 2; break; case 17: CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 4; for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source += 2; break; case 18: CurrentNumberIndex -= (pfont->data.WeightVector.count - 1) * 6; for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source += 2; break; default: for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } if (!OnlyCalcLength) { *dest++ = *source++; *dest++ = *source++; } else { source += 2; } dest_length += 2; break; } } else { for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } if (!OnlyCalcLength) { *dest++ = *source++; *dest++ = *source++; } else { source += 2; } dest_length += 2; } break; case 10: if (CurrentNumberIndex != 0 && SubrsWithMM[Stack[CurrentNumberIndex - 1]] != 0) { int index = Stack[CurrentNumberIndex - 1]; int StackBase = CurrentNumberIndex - 1 - pfont->data.WeightVector.count * SubrsWithMM[index]; CurrentNumberIndex--; /* Remove the subr index */ for (i=0;i < StackBase; i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } for (i=0;i<SubrsWithMM[index];i++) { written = WriteNumber(dest, Stack[StackBase + i]); dest_length += written; if (!OnlyCalcLength) dest += written; } source++; } else { for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } if (!OnlyCalcLength) *dest++ = *source++; else source++; dest_length++; } break; default: for (i = 0;i < CurrentNumberIndex;i++) { written = WriteNumber(dest, Stack[i]); dest_length += written; if (!OnlyCalcLength) dest += written; } if (!OnlyCalcLength) *dest++ = *source++; else source++; dest_length++; } CurrentNumberIndex = 0; } else { /* Number */ if (*source < 247) { Stack[CurrentNumberIndex++] = *source++ - 139; } else { if (*source < 251) { Stack[CurrentNumberIndex] = ((*source++ - 247) * 256) + 108; Stack[CurrentNumberIndex++] += *source++; } else { if (*source < 255) { Stack[CurrentNumberIndex] = ((*source++ - 251) * -256) - 108; Stack[CurrentNumberIndex++] -= *source++; } else { source++; Stack[CurrentNumberIndex] = *source++ << 24; Stack[CurrentNumberIndex] += *source++ << 16; Stack[CurrentNumberIndex] += *source++ << 8; Stack[CurrentNumberIndex++] += *source++; } } } } } source = data->data; state = crypt_charstring_seed; gs_type1_encrypt(source, source, data->size, &state); if (!OnlyCalcLength) { state = crypt_charstring_seed; gs_type1_encrypt(stripped, stripped, dest_length, &state); } return dest_length; }
/* The following 2 routines attempt to parse out Multiple Master 'OtherSubrs' * calls, and replace the multiple arguments to $Blend with the two 'base' * parameters. This works reasonably well but can be defeated. FOr example a * CharString which puts some parameters on the operand stack, then calls a * Subr which puts the remaining parameters on the stack, and calls a MM * OtherSubr (constructions like this have been observed). In general we * work around this by storing the operands on the stack, but it is possible * that the values are calculated (eg x y div) which is a common way to get * float values into the interpreter. This will defeat the code below. * * The only way to solve this is to actually fully interpret the CharString * and any /Subrs it calls, and then emit the result as a non-MM CharString * by blending the values. This would mean writing a new routine like * 'psf_convert_type1_to_type2' (see gdevpsfx.c) or modifying that routine * so that it outputs type 1 CharStrings (which is probably simpler to do). */ static int CheckSubrForMM (gs_glyph_data_t *gdata, gs_font_type1 *pfont) { crypt_state state = crypt_charstring_seed; int code = 0; gs_bytestring *data = (gs_bytestring *)&gdata->bits; byte *source = data->data, *end = source + data->size; int CurrentNumberIndex = 0, Stack[32]; memset(Stack, 0x00, sizeof(Stack)); gs_type1_decrypt(source, source, data->size, &state); if(pfont->data.lenIV) source += pfont->data.lenIV; while (source < end) { if (*source < 32) { /* Command */ switch (*source) { case 12: if (*(source + 1) == 16) { if (CurrentNumberIndex < 1) return gs_error_rangecheck; switch(Stack[CurrentNumberIndex-1]) { case 18: code = 6; break; case 17: code = 4; break; case 16: code = 3; break; case 15: code = 2; break; case 14: code = 1; break; default: code = 0; break; } source += 2; } else { source +=2; } break; default: source++; break; } CurrentNumberIndex = 0; } else { /* Number */ if (*source < 247) { Stack[CurrentNumberIndex++] = *source++ - 139; } else { if (*source < 251) { Stack[CurrentNumberIndex] = ((*source++ - 247) * 256) + 108; Stack[CurrentNumberIndex++] += *source++; } else { if (*source < 255) { Stack[CurrentNumberIndex] = ((*source++ - 251) * -256) - 108; Stack[CurrentNumberIndex++] -= *source++; } else { Stack[CurrentNumberIndex] = *source++ << 24; Stack[CurrentNumberIndex] += *source++ << 16; Stack[CurrentNumberIndex] += *source++ << 8; Stack[CurrentNumberIndex] += *source++; } } } } } state = crypt_charstring_seed; source = data->data; gs_type1_encrypt(source, source, data->size, &state); return code; }