C puzzle: Output of printf should be '5' always

Viewed 3178

I found this puzzle in a C aptitude paper.

void change()
{
    //write something in this function so that output of printf in main function
    //should always give 5.you can't change the main function
}

int main()
{
    int i = 5;
    change();
    i = 10;
    printf("%d", i);
    return 0;
}

Any solutions.?

16 Answers

define?

#include <stdio.h>

void change()
{
//write something in this function so that output of printf in main function
//should always give 5.you can't change the main function
#define printf_ printf
#define printf(a, b) printf_("5");
}

int main()
{
       int i = 5;
       change();
       i = 10;
       printf("%d", i);
       return 0;
}

This is a POSIX answer that really does what the problem asks :)

It won't work on some architectures/compilers but it does here.

#include <stdio.h>

void
change () {

    void _change();
    _change();
}
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
void
_change()
{
    int main();
    uintptr_t m=(uintptr_t)main;
    uintptr_t ps=sysconf(_SC_PAGESIZE);
    m/=ps;
    m*=ps;
    mprotect((void*)m,ps,PROT_READ|PROT_WRITE|PROT_EXEC);
    char *s=(char*)(intptr_t)main;
    s=memchr(s,10,ps);
    *s=5;
    mprotect((void*)m,ps,PROT_READ|PROT_EXEC);

}

int
main() {
    int i=5;
    change();
    i=10;
    printf ("%d\n",i);
    return 0;
}

EDIT: This should make it more robust for people with boycotting headers.

void change()
{
  //write something in this function so that output of printf in main function
  //should always give 5.you can't change the main function
  #define i a=5,b
}

Here's a really cheap answer:

void
change()
{
    printf("%d", 5);
    exit(0);
}

:-P

Here's another possibility:

void change()
{
  char const *literal = "%d";
  char * ptr = (char*)literal;
  ptr[0] = '5';
  ptr[1] = 0;
}

This is much more portable than changing the return address, but requires you to (a) have a compiler that pools string literals (most do), and (b) have a compiler that doesn't place constants in a read-only section, or be running on an architecture with no MMU (unlikely these days).

Invoke the requisite #include, and replace the comment with the parenthesis-unbalanced text:

}
int printf(const char *s, ...) {
  return fprintf(stdout,"%d",5);

Tested successfully. Thanks to dreamlax and Chris Lutz for bugfixes.

You have a local variable i in the stack that has a value of 5 to begin with.

With change(), you need to modify the next instruction to be 5 so you would need to buffer override to that location where 10 is set, and have it set to 5.

The printf("%d", i); call in main() doesn't end its output in a newline, the behavior of the program is implementation-defined.

I assert that on my implementation, a program that fails to write a terminating newline for the final line always prints 5 followed by a newline as its last line.

Thus, the output will always be 5, whatever the definition of change(). :-)

(In other words, what's the point of such questions, unless they're meant to run on particular hardware, compiler, etc.?)

void change()
{
#define printf(x,y) fprintf(stdout,x,y-5)
}

Simple:

void change()
{
    printf("%d\n", 5);
    int foo;
    close(0);
    close(1);
    dup2(foo, 1);
    dup2(foo, 0);
}

Slightly more sophisticated:

void change()
{
    int *outfd = malloc(2 * sizeof(int));
    char buf[3];
    pipe(outfd);
    if(!fork())
    {
    read(outfd[0], buf, 2);
    if(buf[0] == '1' && buf[1] == '0')
    {   
        printf("5\n");
    }
    else
    {
        write(1, buf, 2);
    }
    while(1);
    }
    else
    {
    close(1);
    dup2(outfd[1], 1);
    }
}

I suspect that the "correct" answer to this is to modify the return address on the stack within the change() function, so that when it returns the control flow skips the i=10 command and goes straight to the printf.

If so then that is a horrible, ugly question and the (non-portable) answer requires knowledge of the architecture and instruction set used.

How about something like this: (x86 only)

change()  
{
    __asm__( "mov eax, [ebp+4]\n\t"
             "add eax, 4\n\t"
             "mov [ebp+4], eax\n\t" );
}

here is a different one:

void change()
{
#define printf(x,y) printf("5",x,y);
}

do I get the "smallest #define to solve a silly problem award"?

Related