Изменение адреса возврата функции для перехода по строковому коду - PullRequest
0 голосов
/ 05 июня 2019

Я хочу изменить следующую функцию, чтобы можно было пропустить строку: x = 'b' в основной функции.

#include <stdio.h>

void function (int a, int b, int c) {
  int i, j;
  char buf[5];
  char buffer1[12];  
  int *ret; 
}

int main() {
  char x;
  x = 'a';
  printf ("Hello\n");
  printf ("I am going to skip a statement\n");  
  function(1,2,3);
  x = 'b';
  printf ("By");
  printf("The following value must be the a letter: %c\n",x);
}

Я пытался получить адрес возврата и использовать переменную `ret 'для добавления необходимых байтов, но кажется, что это не правильно.

ret=buffer1+12+4+1;
(*ret)+=4;


В любом случае, x = 'b' все еще выполняется.

Ответы [ 4 ]

2 голосов
/ 05 июня 2019

ret = buffer1 + 12 + 4 + 1;

Это Undefined Behavior ™ , поскольку арифметика указателей вышла из выделения.Теперь компилятор может делать все, что пожелает, вплоть до того, что демоны вылетят из носа.

(* ret) + = 4;

Иgcc получил очень хорошо , обнаружив неопределенное поведение, и довольно неплох, когда приходит время выбирать, что ему нравится.

Если оптимизации включены, он может просто полностью игнорировать оператор, если нетв любом случае, вы, вероятно, неправильно смещены, потому что нет абсолютно никакой гарантии относительно расположения переменных.Будет несколько отступов для выравнивания, и даже порядок может быть другим.И я не уверен, откуда вы взяли +1, но нет разумного макета, в котором это имело бы смысл.

Вы также, похоже, предполагаете 32-битную цель, но большинство Linux полностью 64-битныев эти дни.

1 голос
/ 05 июня 2019

В данный момент, когда я использую свой персональный компьютер и ночью новолуние, приведенный ниже код прекрасно работает (примечание) .Он пропускает 2-ю puts инструкцию и переходит непосредственно к 3-му puts.

#include <stdio.h>
#include <setjmp.h>
#include <stdint.h>

#define can_you_see_what_I_mean() setjmp(jb)
#define might_as_well(task) ((uint32_t*)&jb)[20] = 0x401544; task(jb, 0)

static jmp_buf jb;

int main (void)
{
  puts("I get up");
  if(!can_you_see_what_I_mean())
  {
    might_as_well(longjmp);
  }
  puts("Go ahead and jump");
  puts("Hey you, who said that?");
}

Вывод:

I get up
Hey you, who said that?

(примечание) Я бы никому не рекомендовал использовать этот код для каких-либо целей, поскольку он опирается на крайне дурную практику и содержит бесчисленные формы неопределенного поведения.Это чрезвычайно непереносимо.

0 голосов
/ 06 июня 2019

следующий предложенный код:

  1. чисто компилирует
  2. зависит от оператора в function(), чтобы пропустить оператор: x = 'b';

и теперь предложенный код:

#include <stdio.h>

int function ( void ) 
{
    return 1;
}

int main( void ) 
{
  char x = 'a';
  printf ("Hello\n");
  printf ("I am going to skip a statement\n");  
  if( !function() )
  {
      x = 'b';
  }
  printf ("By");
  printf("The following value must be the a letter: %c\n",x);
}
0 голосов
/ 05 июня 2019

Этот пост может помочь вам решить ваш вопрос с некоторыми оговорками: Проблема в том, что при редактировании jmp_buf или при записи встроенной сборки не переносимо . Я предлагаю вам использовать одну из многих конструкций потока управления (например, if или goto), и, как говорится, посмотрите на это как на отправную точку. Реализация setjmp и longjmp в C без встроенных функций или сборки (получение неправильных возвращаемых значений)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...