Masalah ImportExport dengan destruktor baru Varien_Image_Adapter_Gd2 di 1.9.2.0

23

Bisakah seseorang menjelaskan, untuk apa Kode berikut diperkenalkan antara Magento CE 1.9.1.0 dan 1.9.2.0?

class Varien_Image_Adapter_Gd2:

public function __construct()
{
    // Initialize shutdown function
    register_shutdown_function(array($this, 'destruct'));
}

/**
 * Destroy object image on shutdown
 */
public function destruct()
{
    @imagedestroy($this->_imageHandler);
}

Setelah kedua fungsi tersebut ditambahkan, impor gambar galeri produk kami dengan antarmuka ImportExport berhenti berfungsi. Kesalahan ini disebabkan oleh batas memori (yang keluar menjadi batas ukuran file maks terbuka).

Ide saya adalah, bahwa file yang dibuka oleh impor tidak akan ditutup dengan benar.

Saya juga melihat bahwa ada beberapa destruct()fungsi kosong yang diperkenalkan ( Mage_ImportExport_Model_Import_Adapter_Abstract) - tetapi memperluasnya agar sesuai dengan logika induk tidak membantu.

Achim Rosenhagen
sumber

Jawaban:

14

Itu terlihat seperti mereka berusaha memastikan untuk menghancurkan sumber gambar, tetapi malah menyebabkan kebocoran memori. Saya tidak bisa memikirkan alasan yang valid untuk kode ini, jujur, tapi saya bisa menjelaskan apa yang telah diubah:

Awalnya, imagedestroy()akan dipanggil dalam desctructor__destruct()

function __destruct()
{
    @imagedestroy($this->_imageHandler);
}

Destructor disebut kapanpun pemulung sampah PHP menghancurkan objek yang tidak digunakan (yaitu objek dalam memori yang tidak direferensikan lagi).

Sekarang, imagedestroy()sebaliknya dipanggil dalam fungsi shutdown dan karena ini adalah panggilan balik ke metode Varien_Image_Adapter_Gd2objek, itu bahkan tidak dapat menjadi sampah yang dikumpulkan sampai akhir. Dengan cara ini semua sumber gambar tetap terbuka sampai eksekusi skrip selesai.

Fabian Schmengler
sumber
Terima kasih atas penjelasannya - inilah yang saya pikirkan. Jadi secara keseluruhan, kode yang diperkenalkan ini membuat sebagian besar impor tidak berguna di 1.9.2. di mataku. Semoga ini akan segera diperbaiki. Adakah saran untuk membuka laporan Bug?
Achim Rosenhagen
6

Memiliki masalah yang sama dengan Magento 1.9.2.0 saya ...

Saya hanya mendapatkan ini untuk bekerja dengan mengubah Varien_Image_Adapter_Gd2 di /lib/Varien/Image/Adapter/Gd2.phpsebagai berikut:

public function __construct()
{
    // Initialize shutdown function
    // register_shutdown_function(array($this, 'destruct'));
}

/**
 * Destroy object image on shutdown
 */
public function __destruct()
{
    @imagedestroy($this->_imageHandler);
}
  • hapus baris dengan register_shutdown_function (atau beri komentar)
  • ubah nama fungsi yang dirusak menjadi __destruct

Saya telah mengatur memory_limit kembali ke 1G (sebelumnya saya menaikkan hingga 32GB) dan sekarang berfungsi ...

Proyek ini mengimplementasikan prosedur tersebut dengan cara yang ramah dan bersahabat. Cukup pasang dengan komposer dan Anda siap melakukannya.

dkr
sumber
Ini tidak benar-benar menjawab pertanyaan. Jika Anda memiliki pertanyaan yang berbeda, Anda dapat menanyakannya dengan mengeklik Ajukan Pertanyaan . Anda juga dapat menambahkan hadiah untuk menarik lebih banyak perhatian ke pertanyaan ini setelah Anda memiliki reputasi yang cukup .
Rajeev K Tomy
Ya, ini tidak menjawab pertanyaan tetapi akan membantu orang yang membutuhkan solusi sementara dan tidak ada diskusi
dkr
memperbaiki masalah dengan konsumsi memori selama impor. Menarik, apakah Magento menguji entah bagaimana apa yang mereka rilis?
klipach
Ini tidak hanya menyelesaikan masalah impor. Ini memecahkan makan memori besar dengan proses yang membuat / membuat ulang cache dan mengubah ukuran versi untuk setiap gambar produk. Jika saya mengunggah gambar png di produk saya, tanpa "peretasan" ini saya tidak bisa bekerja dan saya mendapatkan banyak memori yang hilang kesalahan.
Simbus82
Hari ini saya menemukan saran ini. Saya menerapkannya dan kebocoran memori hilang. Kemudian saya membuat github.com/borasocom-team/magento-gd2-memoryleak ini untuk memasangnya dengan cara yang bersih.
Dr. Gianluigi Zane Zanettini
5

Itu adalah bagian dari memperbaiki masalah keamanan dengan unserialize. Metode ajaib seperti __destruct memiliki masalah inheren dengan serialisasi.

Kami telah melihat eksploit yang diusulkan yang menggunakan serialisasi dan __destruct untuk membuat file dalam sistem file - dan perubahan ini (Anda akan melihat lebih banyak perubahan serupa di tempat lain) dilakukan untuk menghindari hal ini.

Apakah ini menyebabkan kebocoran memori atau hanya menggunakan lebih banyak memori hingga skrip selesai?

/security/77549/is-php-unserialize-exploitable-without-any- Interesting-methods

Piotr Kaminski
sumber
Terima kasih untuk konteksnya. Apakah perubahan khusus ini dilakukan untuk mencegah eksploitasi tertentu atau hanya untuk memastikan?
Fabian Schmengler
Dan tidak, itu mungkin hanya membuat skrip mengkonsumsi lebih banyak memori, bukan kebocoran memori nyata
Fabian Schmengler
Ini menyebabkan kebocoran memori yang besar terutama ketika mengimpor gambar, karena itu akan membuat semua file gambar terbuka sampai akhir pemrosesan impor. Dengan cara ini kami hanya dapat mengimpor sekitar 50 produk (sebelum kami dapat melakukan impor> 2k tanpa terasa). Saya menjalankan pengujian pada VM lokal dengan RAM 8G dan semua file sumber sekitar 300KB. Sebelum mengubah memori yang digunakan oleh PHP rermains di 1k selama seluruh impor.
Achim Rosenhagen
fschmengler benar - ini mungkin bukan 'kebocoran memori' tetapi konsumsinya naik ke atas bukit ;-)
Achim Rosenhagen
1
@Alex, terima kasih atas sarannya. Saya membalikkannya. Sekarang, kebocoran memori hilang, tetapi tidak ada solusi untuk masa depan.
Arne
4

Jadi saya memang meningkatkan bug dengan Magento termasuk "solusi" yang harus berurusan dengan masalah penggunaan memori dalam proses impor gambar.

Solusinya dapat ditemukan di github di bawah https://github.com/sitewards/import_image_memory_leak_fix tetapi ide dasarnya adalah.

Memperbaiki Mage_Catalog_Helper_Image::validateUploadFileuntuk benar-benar memanggil destructmetode pada prosesor gambar. Sayangnya sepertinya default Varien_Imagetidak berurusan dengan destructjadi kami harus menambahkan kelas kami sendiri yang tidak.

<?php
/**
 * @category    Sitewards
 * @package     Sitewards_ImportImageMemoryLeakFix
 * @copyright   Copyright (c) Sitewards GmbH (http://www.sitewards.com/)
 */
class Sitewards_ImportImageMemoryLeakFix_Model_Destructable_Image extends Varien_Image
{
    /**
     * Constructor,
     * difference from original constructor - we register a destructor here.
     *
     * @param string $sFileName
     * @param Varien_Image_Adapter $oAdapter Default value is GD2
     */
    public function __construct($sFileName = null, $oAdapter = Varien_Image_Adapter::ADAPTER_GD2)
    {
        parent::__construct($sFileName, $oAdapter);

        // Initialize shutdown function
        register_shutdown_function(array($this, 'destruct'));
    }

    /**
     * Destroy object image on shutdown
     */
    public function destruct()
    {
        $oAdapter = $this->_getAdapter();
        if (method_exists($oAdapter, 'destruct')) {
            $oAdapter->destruct();
        } else {
            Mage::log('Image can not be destructed properly, adapter doesn\'t support the method.');
        }
    }
}

Dan kemudian menulis ulang pembantu.

<?xml version="1.0"?>
<config>
    <modules>
        <Sitewards_ImportImageMemoryLeakFix>
            <version>0.1.0</version>
        </Sitewards_ImportImageMemoryLeakFix>
    </modules>
    <global>
        <models>
            <sitewards_importimagememoryleakfix>
                <class>Sitewards_ImportImageMemoryLeakFix_Model</class>
            </sitewards_importimagememoryleakfix>
        </models>
        <helpers>
            <catalog>
                <rewrite>
                    <image>Sitewards_ImportImageMemoryLeakFix_Helper_Catalog_Helper_Image</image>
                </rewrite>
            </catalog>
        </helpers>
    </global>
</config>

Dan fungsi baru memanggil kelas gambar baru yang dapat dirusak.

<?php
/**
 * @category    Sitewards
 * @package     Sitewards_ImportImageMemoryLeakFix
 * @copyright   Copyright (c) Sitewards GmbH (http://www.sitewards.com/)
 */
class Sitewards_ImportImageMemoryLeakFix_Helper_Catalog_Helper_Image extends Mage_Catalog_Helper_Image
{
    /**
     * Check - is this file an image
     *
     * Difference from original method - we destroy the image object here,
     * i.e. we are not wasting memory, without that fix product import with images
     * easily goes over 4Gb on memory with just couple hundreds of products.
     *
     * @param string $sFilePath
     *
     * @return bool
     * @throws Mage_Core_Exception
     */
    public function validateUploadFile($sFilePath) {
        if (!getimagesize($sFilePath)) {
            Mage::throwException($this->__('Disallowed file type.'));
        }

        /** @var Sitewards_ImportImageMemoryLeakFix_Model_Destructable_Image $oImageProcessor */
        $oImageProcessor = Mage::getModel('sitewards_importimagememoryleakfix/destructable_image', $sFilePath);
        $sMimeType       = $oImageProcessor->getMimeType();
        $oImageProcessor->destruct();

        return $sMimeType !== null;
    }
}
David Manners
sumber