# Introduction

You're probably familiar with zip bombs, XML bombs, etc. Put simply, they are (relatively) small files which produce enormous output when interpreted by naïve software. The challenge here is to abuse a compiler in the same way.

# Challenge

Write some source code which occupies 512 bytes or less and which compiles into a file which occupies the most possible space. Largest output file wins!

# Rules

OK, so there are a few important clarifications, definitions and restrictions;

• The output of the compilation must be an ELF file, a Windows Portable Executable (.exe), or virtual bytecode for the JVM or .Net's CLR (other types of virtual bytecode are also likely to be OK if asked for). Update: Python's .pyc / .pyo output also counts.
• If your language-of-choice can't be compiled directly into one of those formats, transpilation followed by compilation is also allowed (Update: you can transpile multiple times, just so long as you never use the same language more than once).
• Your source code can consist of multiple files, and even resource files, but the summed size of all these files must not exceed 512 bytes.
• You cannot use any other input than your source file(s) and the standard library of your language-of-choice. Static linking standard libraries is OK when it's supported. Specifically, no third party libraries or OS libraries.
• It must be possible to invoke your compilation using a command or series of commands. If you require specific flags when compiling, these count towards your byte limit (e.g. if your compile line is gcc bomb.c -o bomb -O3 -lm, the -O3 -lm part (7 bytes) will be counted (note the initial leading space isn't counted).
• Preprocessors are permitted only if they are a standard compilation option for your language.
• The environment is up to you, but in the interests of making this verifiable, please stick to recent (i.e. available) compiler versions and operating systems (and obviously specify which you're using).
• It must compile without errors (warnings are OK), and crashing the compiler doesn't count for anything.
• What your program actually does is irrelevant, though it can't be anything malicious. It doesn't even have to be able to start.

# Example 1

The C program

main(){return 1;}


Compiled with Apple LLVM version 7.0.2 (clang-700.1.81) on OS X 10.11 (64-bit):

clang bomb.c -o bomb -pg


Produces a file of 9228 bytes. The total source size is 17+3 (for the -pg) = 20 bytes, which is easily within size limit.

# Example 2

The Brainfuck program:

++++++[->++++++++++++<]>.----[--<+++>]<-.+++++++..+++.[--->+<]>-----.--
-[-<+++>]<.---[--->++++<]>-.+++.------.--------.-[---<+>]<.[--->+<]>-.


Transpiled with awib to c with:

./awib < bomb.bf > bomb.c


Then compiled with Apple LLVM version 7.0.2 (clang-700.1.81) on OS X 10.11 (64-bit):

clang bomb.c


Produces a file of 8464 bytes. The total input here is 143 bytes (since @lang_c is the default for awib it didn't need to be added to the source file, and there are no special flags on either command).

Also note that in this case, the temporary bomb.c file is 802 bytes, but this counts towards neither the source size nor the output size.

# Final Note

If an output of more than 4GB is achieved (perhaps if somebody finds a turing complete preprocessor), the competition will be for the smallest source which produces a file of at least that size (it's just not practical to test submissions which get too big).

• If using a transpiler, does the output source code need to be under 512 bytes as well as the input source code? – trichoplax Jan 11 '16 at 23:57
• Is repeated transpilation allowed? – orlp Jan 12 '16 at 0:02
• @LegionMammal978 yes it has to produce one of the file types I specified. But if you think you've found something which is more virtual-machine than interpreted-language, ask about it specifically and it's possible I'll allow it (it's a bit subjective so I wanted to be very restrictive to begin, with the option of opening it up) – Dave Jan 12 '16 at 0:21
• @trichoplax I wasn't aware of that, but from some reading it looks like yes; compiling to Python bytecode absolutely counts. So for python, the output size would be the sum total size of all your pyc/pyo files. I'll update the question soon with these comment-based updates. – Dave Jan 12 '16 at 0:58
• @MartinRosenau - WGroleau already asked a similar question; it's standard in coding challenges that you can use anything which already existed when the challenge began. – Dave Jan 17 '16 at 17:09

# C, (14 + 15) = 29 byte source, 17,179,875,837 (16 GB) byte executable

Thanks to @viraptor for 6 bytes off.

Thanks to @hvd for 2 bytes off and executable size x4.

This defines the main function as a large array and initialises its first element. This causes GCC to store the entire array in the resulting executable.

Because this array is bigger than 2GB, we need to provide the -mcmodel=medium flag to GCC. The extra 15 bytes are included in the score, as per the rules.

main[-1u]={1};


Don't expect this code to do anything nice when run.

Compile with:

gcc -mcmodel=medium cbomb.c -o cbomb


It took me a while to get round to testing @hvd's suggestion - and to find a machine with enough juice to handle it. Eventually I found a old non-production RedHat 5.6 VM with 10GB RAM, 12GB swap, and /tmp set to a large local partition. GCC version is 4.1.2. Total compile time about 27 minutes.

Due to the CPU and RAM load, I recommend against doing this compile on any remotely production-related machine.

• – Digital Trauma Jan 12 '16 at 1:19
• I'm playing against my solution here, but... you don't need a. You can just use main[1<<30]={1}; – viraptor Jan 12 '16 at 1:41
• Oh my. This is evil. X froze for several minutes trying to compile that code. I was starting to look for another computer to possibly ssh back in and kill the gcc process before it finally came back to life. Btw. If you want a larger value than 1<<30 then 7<<28 could be an option. – kasperd Jan 12 '16 at 19:55
• >4gb? That escalated quickly – Wayne Werner Jan 13 '16 at 1:28
• In case anyone else is wondering why this compiles: stackoverflow.com/questions/34764796/… – T. C. Jan 13 '16 at 11:40

# Python 3, 13 byte source, 9,057,900,463 byte (8.5GiB) .pyc-file

(1<<19**8,)*2


Edit: Changed the code to the version above after I realized the rules say output size beyond 4GiB doesn't matter, and the code for this one is ever so slightly shorter; The previous code - and more importantly the explanation - can be found below.

# Python 3, 16 byte source, >32TB .pyc-file (if you have enough memory, disk space and patience)

(1<<19**8,)*4**7


Explanation: Python 3 does constant folding, and you get big numbers fast with exponentation. The format used by .pyc files stores the length of the integer representation using 4 bytes, though, and in reality the limit seems to be more like 2**31, so using just exponentation to generate one big number, the limit seems to be generating a 2GB .pyc file from an 8 byte source. (19**8 is a bit shy of 8*2**31, so 1<<19**8 has a binary representation just under 2GB; the multiplication by eight is because we want bytes, not bits)

However, tuples are also immutable and multiplying a tuple is also constant folded, so we can duplicate that 2GB blob as many times as we want, up to at least 2**31 times, probably. The 4**7 to get to 32TB was chosen just because it was the first exponent I could find that beat the previous 16TB answer.

Unfortunately, with the memory I have on my own computer, I could test this only up to a multiplier of 2, ie. (1<<19**8,)*2, which generated a 8.5GB file, which I hope demonstrates that the answer is realistic (ie. the file size isn't limited to 2**32=4GB).

Also, I have no idea why the file size I got when testing was 8.5GB instead of the 4GB-ish I expected, and the file is big enough that I don't feel like poking around it at the moment.

• +1, but why don't (1<<19**8,)*2? 4GB is enough. – Xwtek Jan 14 '16 at 10:38
• @ChristianIrwan: Yeah, I'd forgotten that rule, only realized it a few minutes ago and haven't figured out what kind of edit I should make yet. :-) – Aleksi Torhamo Jan 14 '16 at 10:46
• Nice. Since this is only 13 bytes, we finally have a challenger to the first-posted answer! I was only able to confirm 1<<18 on my machine (1.5GB) but I'll test it on linux later, where I expect it will work with the full 8GB (not going to try the 32TB version!) – Dave Jan 17 '16 at 17:22
• IIRC, python uses 30 bits per 32-bit word in its integer representation – user16488 Oct 6 '16 at 23:34
• @AnshumanKumar: In Python interactive shell? If you put it into a variable (so eg. v = (1<<19**8,)*4**7), and you have enough free memory (a bit over 2GB), nothing much - it'll take a second or two to complete, and the process will use that much more memory. If you don't put it into a variable, Python will try to display the number, which means it needs to convert it to decimal first - which will take some time (and more memory) with a number that big. How long? Depends on the computer, but on the order of a year. But after that, it should finally print the multi-gigabyte output for you! – Aleksi Torhamo Feb 17 at 19:58

# C#, about 1 min to compile, 28MB output binary:

class X<A,B,C,D,E>{class Y:X<Y,Y,Y,Y,Y>{Y.Y.Y.Y.Y.Y.Y.Y.Y y;}}


Adding more Y's will increase the size exponentially.

An explanation by Pharap as per @Odomontois' request:

This answer is abusing inheritance and type parameters to create recursion. To understand what's happening, it's easier to first simplify the problem. Consider class X<A> { class Y : X<Y> { Y y; } }, which generates the generic class X<A>, which has an inner class Y. X<A>.Y inherits X<Y>, hence X<A>.Y also has an inner class Y, which is then X<A>.Y.Y. This then also has an inner class Y, and that inner class Y has an inner class Y etc. This means that you can use scope resolution (.) ad infinitum, and every time you use it, the compiler has to deduce another level of inheritance and type parameterisation.

By adding additional type parameters, the work the compiler has to do at each stage is further increased.

Consider the following cases:
In class X<A> { class Y : X<Y> { Y y;} } type param A has a type of X<A>.Y.
In class X<A> { class Y : X<Y> { Y.Y y;} } type param A has a type of X<X<A>.Y>.Y.
In class X<A> { class Y : X<Y> { Y.Y.Y y;} } type param A has a type of X<X<X<A>.Y>.Y>.Y.
In class X<A,B> { class Y : X<Y,Y> { Y y;} } type param A is X<A,B>.Y and B is X<A,B>.Y.
In class X<A> { class Y : X<Y> { Y.Y y;} } type param A is X<X<A,B>.Y, X<A,B>.Y>.Y and B is X<X<A,B>.Y, X<A,B>.Y>.Y.
In class X<A> { class Y : X<Y> { Y.Y.Y y;} } type param A is X<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y and B is X<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y.

Following this pattern, one can only imagine1 the work the compiler would have to do to to deduce what A to E are in Y.Y.Y.Y.Y.Y.Y.Y.Y in the definition class X<A,B,C,D,E>{class Y:X<Y,Y,Y,Y,Y>{Y.Y.Y.Y.Y.Y.Y.Y.Y y;}}.

1 You could figure it out, but you'd need a lot of patience, and intellisense won't help you out here.

• This is more like the sort of insanity I was expecting! Looks like I'm off to reinstall Mono… – Dave Jan 12 '16 at 2:00
• Can you provide an explanation of such notorious effect? – Odomontois Jan 12 '16 at 8:58
• +1 for doing more than just initializing a large array. – Stig Hemmer Jan 12 '16 at 9:18
• Here's an example using Try Roslyn and just 3 Ys. – Kobi Jan 12 '16 at 12:21
• I saw this question and immediately thought of you. Nice! – Eric Lippert Jan 13 '16 at 16:14

If an output of more than 4GB is achieved (perhaps if somebody finds a turing complete preprocessor), the competition will be for the smallest source which produces a file of at least that size (it's just not practical to test submissions which get too big).

"Template Haskell" allows Haskell code to be generated at compile-time using Haskell, and is hence a turing complete pre-processor.

Here's my attempt, parameterised by an arbitrary numerical expression FOO:

import Language.Haskell.TH;main=print $(ListE .replicate FOO<$>[|0|])


The magic is the code inside the "splice" $(...). This will be executed at compile time, to generate a Haskell AST, which is grafted on to the program's AST in place of the splice. In this case, we make a simple AST representing the literal 0, we replicate this FOO times to make a list, then we use ListE from the Language.Haskell.TH module to turn this list of ASTs into one big AST, representing the literal [0, 0, 0, 0, 0, ...]. The resulting program is equivalent to main = print [0, 0, 0, ...] with FOO repetitions of 0. To compile to ELF: $ ghc -XTemplateHaskell big.hs
[1 of 1] Compiling Main             ( big.hs, big.o )

## C, 284 bytes + 2 for the -c in gcc bomb.c -o bomb.o -c; output: 2 147 484 052 bytes

#define a 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
#define b a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
#define c b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b
#define d c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
#define e d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d
#define f e,e,e,e,e,e,e,e,e,e,e,e,e,e,e,e
__int128 x[]={f,f,f,f,f,f,f,f};


# Boo, way more than you can expect from this

macro R(e as int):for i in range(9**e):yield R.Body
x = 0
R 99:++x

• This looks like Mason Wheeler's answer with a few small changes (??). Did you reach the same answer independently or is there something important in the values you changed (if so, please edit the answer to explain why they are important). – Dave Oct 24 '17 at 17:20

Python 3:

9**9**9**9**9


Tetration bomb

• You should indicate how many bytes the output is, to see how your entry compares to others. – Sanchises Mar 29 '18 at 9:09
• Welcome to PPCG! It seems you've accidentally created two accounts and posted this answer twice. I've removed the other answer. As Sanchises said, this challenge is scored by the size of the compiled program. So you should include that size in your answer as it's the primary score. Also note that the actual program won't be very big, only the expression you're creating in memory, so you might want to think about a different approach. – Martin Ender Mar 29 '18 at 10:34
• @MartinEnder due to how Python evaluates some expressions at compile time and stores numbers in arbitrary precision, this will (in theory) have a rather a large executable. But as noted by Aleksi Torhamo (who used the same technique for part of his answer), this has a limit somewhere around 2GB, so I'd expect that this code as-written probably won't compile (though I haven't checked). If the OP can get it to compile and posts the compiled size (along with the command needed to generate it), then it's valid. The similarity to Aleksi's existing answer looks like coincidence to me. – Dave Mar 29 '18 at 18:09

PHP 7.1:

const X="x",Y=X.X.X.X.X.X.X.X,Z=Y.Y.Y.Y.Y.Y.Y.Y,A=Z.Z.Z.Z.Z.Z.Z.Z,B=A.A.A.A.A.A.A.A,C=B.B.B.B.B.B.B.B,D=C.C.C.C.C.C.C.C,E=D.D.D.D.D.D.D.D,F=E.E.E.E.E.E.E.E,G=F.F.F.F.F.F.F.F;


. is the concatenation operator, and PHP's compiler will try to do constant folding where possible, so it will construct a huge string and store it in PHP's internal bytecode. (I think you can get this written to a file with newer versions.) This is only as efficient as a classic XML entity bomb unfortunately. You'd need a few more repetitions to get to the gigabyte range.

The interesting part is that by default the worst that'll happen is seeing an error like:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 50331680 bytes) in Command line code on line 1


PHP's web-orientedness means it has a memory limit by default!