Dynamic and Static Variables in C
Variable declarations can be outside all functions or inside a function
Declarations outside all functions are global and in fixed memory locations
    The static declaration declares a variable outside a function to be a “file global” (cannot be referenced by code in other source files)
Declarations within a block statement {} (function body or block statement nested within a function body):
    Are dynamically allocated, unless declared static
    Are allocated memory when program execution enters the block
    Memory is released when execution exits the block
    If a function calls itself (directly or indirectly), it gets a new set of dynamic variables (called a stack frame)
    This is handled no differently from any other call to the function
You have problem, the variable result[] is a variable that has been allocated in side the function — whose lifetime extends across the entire run of the function(allocated at the stack!) because of that you need to make the result Dynamic variable 
Fix code:
#include <stdio.h>
#include <string.h>
char* substr(char *source, int start, int length)
{
    char* result;
    char *r;
    result=(char*)malloc(sizeof(char)*10);
    r = result;
    strncpy(result, source+start, length);
    printf("substr: %s\n", r);
    return r;
}
int main()
{
    char* r=substr("HELLO", 1, 2);
    printf("main: %s\n",r );
    free(r)//Don't forget to free it!
}
OR you can make result[] global variable like this:
#include <stdio.h>
#include <string.h>
char result[10];//<======Global
char* substr(char *source, int start, int length)
{
    char *r=result;
    r = result;
    strncpy(result, source+start, length);
    printf("substr: %s\n", r);
    return r;
}
int main()
{
    printf("main: %s\n",substr("HELLO", 1, 2));
}