DrKLO/Telegram · error

%s: can't determine size of %s

Error message

%s: can't determine size of %s

What it means

After opening the ICC profile file, jpegtran determines its size via fseek(SEEK_END), ftell(), and fseek(SEEK_SET) at jpegtran.c:509-511. If any of these three calls fails or ftell returns less than 1, the file size cannot be determined. This typically happens when the ICC 'file' is not a regular seekable file.

Source

Thrown at TMessagesProj/jni/mozjpeg/jpegtran.c:512

    if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
      fprintf(stderr, "%s: can't open %s for reading\n", progname,
              argv[file_index]);
      exit(EXIT_FAILURE);
    }
  } else {
    /* default input file is stdin */
    fp = read_stdin();
  }

  if (icc_filename != NULL) {
    if ((icc_file = fopen(icc_filename, READ_BINARY)) == NULL) {
      fprintf(stderr, "%s: can't open %s\n", progname, icc_filename);
      exit(EXIT_FAILURE);
    }
    if (fseek(icc_file, 0, SEEK_END) < 0 ||
        (icc_len = ftell(icc_file)) < 1 ||
        fseek(icc_file, 0, SEEK_SET) < 0) {
      fprintf(stderr, "%s: can't determine size of %s\n", progname,
              icc_filename);
      exit(EXIT_FAILURE);
    }
    if ((icc_profile = (JOCTET *)malloc(icc_len)) == NULL) {
      fprintf(stderr, "%s: can't allocate memory for ICC profile\n", progname);
      fclose(icc_file);
      exit(EXIT_FAILURE);
    }
    if (fread(icc_profile, icc_len, 1, icc_file) < 1) {
      fprintf(stderr, "%s: can't read ICC profile from %s\n", progname,
              icc_filename);
      free(icc_profile);
      fclose(icc_file);
      exit(EXIT_FAILURE);
    }
    fclose(icc_file);
    if (copyoption == JCOPYOPT_ALL)
      copyoption = JCOPYOPT_ALL_EXCEPT_ICC;

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Ensure the ICC profile is a regular seekable file: `stat(icc_path)` and check S_ISREG(st_mode)
  2. Copy the ICC profile to local storage (e.g. app internal dir) before passing it
  3. If the data comes from a stream, write it to a temp file first, then pass that temp file path

Example fix

// before
// icc_path is a pipe or FIFO

// after
// copy to a regular temp file first
int fd = open(icc_tmp, O_CREAT|O_WRONLY, 0600);
write(fd, icc_data, icc_data_len);
close(fd);
// now pass icc_tmp to jpegtran -icc
Defensive patterns

Strategy: validation

Validate before calling

// Ensure ICC file is a regular seekable file
int validate_icc_seekable(const char *path) {
    struct stat st;
    if (stat(path, &st) != 0) return -1;
    if (!S_ISREG(st.st_mode)) return -1; // reject pipes, FIFOs, devices
    // verify it's seekable
    FILE *f = fopen(path, "rb");
    if (!f) return -1;
    if (fseek(f, 0, SEEK_END) != 0) { fclose(f); return -1; }
    long sz = ftell(f);
    fclose(f);
    if (sz < 1) return -1;
    return 0;
}

Prevention

When it happens

Trigger: Passing a pipe, FIFO, socket, or /dev/stdin as the ICC profile path. A filesystem that doesn't support seeking. A file that was truncated to zero bytes between open and fseek.

Common situations: ICC profile is piped: `jpegtran -icc <(cat profile.icc)`. On Android, the path resolves to a special device file. The ICC file is on a network mount with interrupted connectivity.

Related errors


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/8fa029d882360abe. Report an issue: GitHub.