{"record":{"id":"6874d1987a7819a7","repo":"DrKLO/Telegram","slug":"memory-allocation-failure-n","errorCode":null,"errorMessage":"Memory allocation failure!\\n","messagePattern":"Memory allocation failure!\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"TMessagesProj/jni/mozjpeg/yuvjpeg.c","lineNumber":171,"sourceCode":"    return 1;\n  }\n\n  fseek(yuv_fd, 0, SEEK_END);\n  yuv_size = ftell(yuv_fd);\n  fseek(yuv_fd, 0, SEEK_SET);\n\n  /* Check that the file size matches 4:2:0 yuv. */\n  if (yuv_size !=\n   (size_t)luma_width*luma_height + 2*chroma_width*chroma_height) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"Unexpected input format!\\n\");\n    return 1;\n  }\n\n  yuv_buffer = malloc(yuv_size);\n  if (!yuv_buffer) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"Memory allocation failure!\\n\");\n    return 1;\n  }\n\n  if (fread(yuv_buffer, yuv_size, 1, yuv_fd) != 1) {\n    fprintf(stderr, \"Error reading yuv file\\n\");\n  };\n\n  fclose(yuv_fd);\n\n  frame_width = (luma_width + (16 - 1)) & ~(16 - 1);\n  frame_height = (luma_height + (16 - 1)) & ~(16 - 1);\n\n  jpg_buffer =\n   malloc(frame_width*frame_height + 2*(frame_width/2)*(frame_height/2));\n  if (!jpg_buffer) {\n    free(yuv_buffer);\n    fprintf(stderr, \"Memory allocation failure!\\n\");\n    return 1;","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/DrKLO/Telegram/blob/45ab8f4308496e1f01026a97fcdb0d58a5274474/TMessagesProj/jni/mozjpeg/yuvjpeg.c#L153-L189","documentation":"Thrown by a YUV-to-JPEG conversion utility when malloc() fails to allocate yuv_buffer for the raw YUV frame data. The allocation size (yuv_size) is the full 4:2:0 planar frame: luma_width*luma_height + 2*chroma_width*chroma_height. This is a fatal, non-recoverable path — the function closes the YUV file handle and returns 1 immediately.","triggerScenarios":"malloc(yuv_size) returns NULL. Occurs when the parsed YUV dimensions produce an extremely large yuv_size, when the process is already near its memory limit, or on 32-bit builds where size_t cannot represent huge frames (though the prior size check passes, the heap is still exhausted).","commonSituations":"Processing very high-resolution video frames (e.g. 4K/8K YUV) on a memory-constrained Android device; running under the Telegram JNI memory ceiling; a malformed YUV header reporting inflated dimensions; device under memory pressure from other apps.","solutions":["Verify the YUV source reports sane dimensions before calling the converter; reject or downscale frames whose computed yuv_size exceeds an available-memory budget.","Reduce the input resolution or process in tiled/striped chunks instead of one whole-frame allocation.","Confirm the device has enough free heap; on Android check ActivityManager.getMemoryInfo() before invoking the native path.","If building for 32-bit, switch to a 64-bit ABI so size_t and the virtual address space can handle large frames."],"exampleFix":"// before\nyuv_buffer = malloc(yuv_size);\nif (!yuv_buffer) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"Memory allocation failure!\\n\");\n    return 1;\n}\n\n// after: bound the allocation against available memory before trying\nif (yuv_size > MAX_SAFE_YUV_BYTES || yuv_size > get_free_heap_bytes()) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"YUV frame too large to allocate (%zu bytes)\\n\", yuv_size);\n    return 1;\n}\nyuv_buffer = malloc(yuv_size);\nif (!yuv_buffer) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"Memory allocation failure!\\n\");\n    return 1;\n}","handlingStrategy":"validation","validationCode":"// Validate the computed YUV size against available heap before malloc.\nsize_t need = (size_t)luma_width*luma_height + 2*(size_t)chroma_width*chroma_height;\nlong free_bytes = get_free_heap_bytes(); /* platform-specific, e.g. mallinfo/ActivityManager */\nif (need > MAX_SAFE_YUV_BYTES || (free_bytes > 0 && (size_t)free_bytes < need)) {\n    fclose(yuv_fd);\n    fprintf(stderr, \"YUV frame too large (%zu bytes, %ld free)\\n\", need, free_bytes);\n    return 1;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject or downscale YUV frames whose dimensions produce a buffer larger than a set memory budget.","On Android, check ActivityManager.getMemoryInfo().lowMemory before invoking the native converter.","Prefer tiled/striped processing so you never allocate a full-frame buffer twice."],"tags":["memory","allocation","mozjpeg","yuv","jni","c"],"backgroundTag":null,"analyzedSha":"45ab8f4308496e1f01026a97fcdb0d58a5274474","analyzedAt":"2026-08-14T05:19:30.815Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}