pickle.load - EOFError: Ran out of input

26,915

So, if the error you get is indeed "pickle: run out of input", that propably means you messed your directories in the code above, and are trying to read an empty file with the same name as your obj file is.

Actually, as it is, this line in your code:

self.mainTerminal=pg.image.load(path.join(img_main_folder,self.main_uncode
("tr.obj"))).convert_alpha()

Is completly messed up. Just read it and you can see the problem: you are passing to the main_uncode method just the file name, without directory information. And then, if it would by chance have worked, as I have poitned in the comments a while ago, you would try to use the unserialized image data as a filename from where to read your image. (You or someone else had probably thought that main_uncode should write a temporary image file and writ the image data to that, so that Pygame could read it, but as it is, it is just returning the raw image data in a string).

Threfore, by fixing the above call and passing an actual path to main_uncode, and further modifying it to write the temporary data to a file and return its path would fix the snippets of code above.

Second thing is I can't figure out why do you need this ".obj" file at all. If it is just for "security through obscurity" hopping people get your bundled file can't open the images, that is a thing far from a recommended practice. To sum up just one thing: it will delay legitimate uses of your file (like, you yourself does not seem to be able to use it ), while any attacker with sufficient motivation can still get to it easily. By opening an image, base-64 encoding and pickling it, and doing the reverse process you are doing essentially a no-operation. Even more, a pickle file can serialize and write to disk complex Python objects - but a base64 serialization of an image could be written directly to a file, with no need for pickle.

Third thing: just use with to open all the files, not just the ones you read with the imaging library, Take your time to learn a little bit more about Python.

Share:
26,915
BlackFenix06
Author by

BlackFenix06

I am Italian, not English. I can not do complete sentences like these in English, so I use Google Translate to help me. But sometimes he writes crap. So I look crazy? I'm a person of simple tastes, I'm stupid, but I love computer language. I try to study it myself, I fall in love with Python. Too bad that it is user friendly and free, so unprotected.

Updated on July 09, 2022

Comments

  • BlackFenix06
    BlackFenix06 almost 2 years

    I have an .obj file in which, previously, I transformed an image to base64 and saved with pickle.

    The problem is when I try to load the .obj file with pickle, convert the code into image from base64, and load it with pygame.

    The function that loads the image:

    def mainDisplay_load(self):
        main_folder = path.dirname(__file__)
        img_main_folder = path.join(main_folder, "sd_graphics")
    
        # loadImg
        self.mainTerminal = pg.image.load(path.join(img_main_folder, self.main_uncode("tr.obj"))).convert_alpha()
    

    The function that decodes the file:

    def main_uncode(self, object):
        openFile = open(object, "rb")
        str = pickle.load(openFile)
        openFile.close()
        fileData = base64.b64decode(str)
        return fileData
    

    The error I get when the code is run:

    str = pickle.load(openFile)
    

    EOFError: Ran out of input

    How can I fix it?

    • Python version: 3.6.2
    • Pygame version: 1.9.3

    Update 1

    This is the code I used to create the .obj file:

    import base64, pickle
    
    with open("terminal.png", "rb") as imageFile:
        str = base64.b64encode(imageFile.read())
        print(str)
    
    file_pi = open("tr.obj","wb")
    pickle.dump(str,file_pi)
    file_pi.close()
    
    file_pi2 = open("tr.obj","rb")
    str2 = pickle.load(file_pi2)
    file_pi2.close()
    
    imgdata = base64.b64decode(str2)
    filename = 'some_image.jpg'  # I assume you have a way of picking unique filenames
    with open(filename, 'wb') as f:
        f.write(imgdata)
    

    Once the file is created, it is loaded and a second image is created. This is to check if the image is the same or there are errors in the conversion.

    As you can see, I used part of the code to load the image, but instead of saving it, it is loaded into pygame. And that's where the mistake occurs.

    Update 2

    I finally managed to solve it.

    In the main code:

    def mainDisplay_load(self):
        self.all_graphics = pg.sprite.Group()
        self.graphics_menu = pg.sprite.Group()
    
        # loadImg
        self.img_mainTerminal = mainGraphics(self, 0, 0, "sd_graphics/tr.obj")
    

    In the library containing graphics classes:

    import pygame as pg
    import base64 as bs
    import pickle as pk
    from io import BytesIO as by
    from lib.setting import *
    
    class mainGraphics(pg.sprite.Sprite):
        def __init__(self, game, x, y, object):
            self.groups = game.all_graphics, game.graphics_menu
            pg.sprite.Sprite.__init__(self, self.groups)
            self.game = game
            self.object = object
            self.outputGraphics = by()
    
            self.x = x
            self.y = y
    
            self.eventType()
    
            self.rect = self.image.get_rect()
            self.rect.x = self.x * tilesizeDefault
            self.rect.y = self.y * tilesizeDefault
    
        def eventType(self):
            openFile = open(self.object, "rb")
            str = pk.load(openFile)
            openFile.close()
            self.outputGraphics.write(bs.b64decode(str))
            self.outputGraphics.seek(0)
            self.image = pg.image.load(self.outputGraphics).convert_alpha()
    

    For the question of why I should do such a thing, it is simple:

    any attacker with sufficient motivation can still get to it easily

    Python is free and open.

    On the one hand, we have a person who intentionally goes and modify and recover the hidden data. But if Python is an open language, as with even more complicated and protected languages, the most motivated are able to crack the game or program and retrieve the same data.

    On the other hand, we have a person who knows only the basics, or not even that. A person who cannot access the files without knowing more about the language, or decoding the files.

    So you can understand that decoding files, from my point of view, does not need to be protected from a motivated person. Because even with a more complex and protected language, that motivated person will be able to get what he wants. The protection is used against people who have no knowledge of the language.