程序循环次数太多,并产生奇怪的行为

时间:2016-06-04 01:20:40

标签: c loops

我正在尝试编写一个程序,将十六进制输入转换为base64编码输出。更具体地说,输入:

0x49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d

(这是"我像一个有毒的蘑菇一样杀死你的大脑"在ASCII中 - 这对以后很重要!)

以下代码是我提出的;它可能过于复杂,但在我的脑海里,每一步都是有道理的。现在,它可以使用简单的输入,例如0x4d616e,但不适用于较长的字符串。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

void base64encode(char * data) {

    size_t data_size = strlen(data);
    size_t last_block_size = data_size%3;
    size_t padding_chars = last_block_size==0?0:3-last_block_size;
    size_t num_blocks = last_block_size==0?data_size/3:(data_size/3)+1;

    int i1,i2,i3,i4 = 0;

    uint32_t * blocks = malloc(sizeof(uint32_t)*num_blocks);

    memset(blocks,0,sizeof(uint32_t)*num_blocks);

    for(int i=0; i<strlen(data); i++)
        blocks[i/3] |= data[i] << (2-(i%3))*8;

    for (int i=0; i<num_blocks; i++){
        i1 = (blocks[i] & 0xfc0000) >> 18;
        i2 = (blocks[i] & 0x03f000) >> 12;
        i3 = ((i==num_blocks-1) && (padding_chars==2))?64:(blocks[i] & 0x000fc0) >> 6;
        i4 = ((i==num_blocks-1) && (padding_chars>=1))?64:(blocks[i] & 0x00003f);

        printf("%c%c%c%c",b64[i1],b64[i2],b64[i3],b64[i4]);

    }

    free(blocks);
}

int hex_char_to_raw (char c) {
    switch (c) {
        case '0': return 0x0;
        case '1': return 0x1;
        case '2': return 0x2;
        case '3': return 0x3;
        case '4': return 0x4;
        case '5': return 0x5;
        case '6': return 0x6;
        case '7': return 0x7;
        case '8': return 0x8;
        case '9': return 0x9;
        case 'A': return 0xA;
        case 'B': return 0xB;
        case 'C': return 0xC;
        case 'D': return 0xD;
        case 'E': return 0xE;
        case 'F': return 0xF;
        default: return -1;
    }
}

void hex_to_raw(char * data) {

    for (int i=2; i < strlen(data); i++){
        if ( (data[i]<48) || ((data[i]>57)&&(data[i]<65)) || ((data[i]>70)&&(data[i]<97)) || (data[i]>102) ) {
            printf("ERROR: Invalid Hex Character '%c' in input at character %d\n",data[i],i-1);
            return;
        } else if ( (data[i] <= 102) && (data[i] >= 97) )
            data[i] = data[i]-32; // Transform all lower case letters to corresponding upper case letters
    }

    char * buffer = malloc(sizeof(char)*(strlen(data)-2));

    for (int i=2; i <= strlen(data); i++) {
        if (i != strlen(data))
            buffer[i-2] = data[i];
        else
            buffer[i-2] = '\0';
    }

    printf("%s\n",buffer);

    char * binary = malloc(sizeof(char)*(strlen(buffer)/2));

    printf("%zu %zu %zu %zu\n",sizeof(char)*(strlen(data)-2),sizeof(char)*(strlen(buffer)/2),strlen(buffer), strlen(data));

    for (int i=0; i < strlen(buffer); i=i+2) {
        printf("\ti=%u i/2=%u buffer[i]=%c buffer[i+1]=%c\n",i,i/2,buffer[i],buffer[i+1]);
        binary[i/2] = (hex_char_to_raw(buffer[i]) << 4) | (hex_char_to_raw(buffer[i+1]));
    }

    free(buffer);
    printf("%s\n", binary);

    base64encode(binary);

    free(binary);
}

int main (int argc, char * argv[]) {

    if (argc != 2) {
        printf("usage: %s [input]\n",argv[0]);
        return 0;
    }


    hex_to_raw(argv[1]);

    printf("\n");

    return 0;
}

当我运行此代码时,我得到以下内容:

andrew@Andrews-MacBook-Air  Sat Jun 04 02:11:55  ~/Documents/Cryptopals Challenges/Set 1/Challenge 1 
     ->  ./test 0x49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d
49276D206B696C6C696E6720796F757220627261696E206C696B65206120706F69736F6E6F7573206D757368726F6F6D
96 48 96 98
    i=0 i/2=0 buffer[i]=4 buffer[i+1]=9
    i=2 i/2=1 buffer[i]=2 buffer[i+1]=7
    i=4 i/2=2 buffer[i]=6 buffer[i+1]=D
    i=6 i/2=3 buffer[i]=2 buffer[i+1]=0
    i=8 i/2=4 buffer[i]=6 buffer[i+1]=B
    i=10 i/2=5 buffer[i]=6 buffer[i+1]=9
    i=12 i/2=6 buffer[i]=6 buffer[i+1]=C
    i=14 i/2=7 buffer[i]=6 buffer[i+1]=C
    i=16 i/2=8 buffer[i]=6 buffer[i+1]=9
    i=18 i/2=9 buffer[i]=6 buffer[i+1]=E
    i=20 i/2=10 buffer[i]=6 buffer[i+1]=7
    i=22 i/2=11 buffer[i]=2 buffer[i+1]=0
    i=24 i/2=12 buffer[i]=7 buffer[i+1]=9
    i=26 i/2=13 buffer[i]=6 buffer[i+1]=F
    i=28 i/2=14 buffer[i]=7 buffer[i+1]=5
    i=30 i/2=15 buffer[i]=7 buffer[i+1]=2
    i=32 i/2=16 buffer[i]=2 buffer[i+1]=0
    i=34 i/2=17 buffer[i]=6 buffer[i+1]=2
    i=36 i/2=18 buffer[i]=7 buffer[i+1]=2
    i=38 i/2=19 buffer[i]=6 buffer[i+1]=1
    i=40 i/2=20 buffer[i]=6 buffer[i+1]=9
    i=42 i/2=21 buffer[i]=6 buffer[i+1]=E
    i=44 i/2=22 buffer[i]=2 buffer[i+1]=0
    i=46 i/2=23 buffer[i]=6 buffer[i+1]=C
    i=48 i/2=24 buffer[i]=6 buffer[i+1]=9
    i=50 i/2=25 buffer[i]=6 buffer[i+1]=B
    i=52 i/2=26 buffer[i]=6 buffer[i+1]=5
    i=54 i/2=27 buffer[i]=2 buffer[i+1]=0
    i=56 i/2=28 buffer[i]=6 buffer[i+1]=1
    i=58 i/2=29 buffer[i]=2 buffer[i+1]=0
    i=60 i/2=30 buffer[i]=7 buffer[i+1]=0
    i=62 i/2=31 buffer[i]=6 buffer[i+1]=F
    i=64 i/2=32 buffer[i]=6 buffer[i+1]=9
    i=66 i/2=33 buffer[i]=7 buffer[i+1]=3
    i=68 i/2=34 buffer[i]=6 buffer[i+1]=F
    i=70 i/2=35 buffer[i]=6 buffer[i+1]=E
    i=72 i/2=36 buffer[i]=6 buffer[i+1]=F
    i=74 i/2=37 buffer[i]=7 buffer[i+1]=5
    i=76 i/2=38 buffer[i]=7 buffer[i+1]=3
    i=78 i/2=39 buffer[i]=2 buffer[i+1]=0
    i=80 i/2=40 buffer[i]=6 buffer[i+1]=D
    i=82 i/2=41 buffer[i]=7 buffer[i+1]=5
    i=84 i/2=42 buffer[i]=7 buffer[i+1]=3
    i=86 i/2=43 buffer[i]=6 buffer[i+1]=8
    i=88 i/2=44 buffer[i]=7 buffer[i+1]=2
    i=90 i/2=45 buffer[i]=6 buffer[i+1]=F
    i=92 i/2=46 buffer[i]=6 buffer[i+1]=F
    i=94 i/2=47 buffer[i]=6 buffer[i+1]=D
    i=96 i/2=48 buffer[i]=I buffer[i+1]='
    i=98 i/2=49 buffer[i]=m buffer[i+1]= 
    i=100 i/2=50 buffer[i]=k buffer[i+1]=i
    i=102 i/2=51 buffer[i]=l buffer[i+1]=l
    i=104 i/2=52 buffer[i]=i buffer[i+1]=n
    i=106 i/2=53 buffer[i]=g buffer[i+1]= 
    i=108 i/2=54 buffer[i]=y buffer[i+1]=o
    i=110 i/2=55 buffer[i]=u buffer[i+1]=r
    i=112 i/2=56 buffer[i]=  buffer[i+1]=b
    i=114 i/2=57 buffer[i]=r buffer[i+1]=a
    i=116 i/2=58 buffer[i]=i buffer[i+1]=n
    i=118 i/2=59 buffer[i]=  buffer[i+1]=l
    i=120 i/2=60 buffer[i]=i buffer[i+1]=k
    i=122 i/2=61 buffer[i]=e buffer[i+1]= 
    i=124 i/2=62 buffer[i]=a buffer[i+1]= 
    i=126 i/2=63 buffer[i]=p buffer[i+1]=o
    i=128 i/2=64 buffer[i]=i buffer[i+1]=s
    i=130 i/2=65 buffer[i]=o buffer[i+1]=n
    i=132 i/2=66 buffer[i]=o buffer[i+1]=u
    i=134 i/2=67 buffer[i]=s buffer[i+1]= 
    i=136 i/2=68 buffer[i]=m buffer[i+1]=u
    i=138 i/2=69 buffer[i]=s buffer[i+1]=h
    i=140 i/2=70 buffer[i]=r buffer[i+1]=o
    i=142 i/2=71 buffer[i]=o buffer[i+1]=m
    i=144 i/2=72 buffer[i]=? buffer[i+1]=?
    i=146 i/2=73 buffer[i]=? buffer[i+1]=?
    i=148 i/2=74 buffer[i]=? buffer[i+1]=?
    i=150 i/2=75 buffer[i]=? buffer[i+1]=?
    i=152 i/2=76 buffer[i]=? buffer[i+1]=?
    i=154 i/2=77 buffer[i]=? buffer[i+1]=?
    i=156 i/2=78 buffer[i]=? buffer[i+1]=?
    i=158 i/2=79 buffer[i]=? buffer[i+1]=?
    i=160 i/2=80 buffer[i]=? buffer[i+1]=?
    i=162 i/2=81 buffer[i]=? buffer[i+1]=?
    i=164 i/2=82 buffer[i]=? buffer[i+1]=?
    i=166 i/2=83 buffer[i]=? buffer[i+1]=?
    i=168 i/2=84 buffer[i]=? buffer[i+1]=?
    i=170 i/2=85 buffer[i]=? buffer[i+1]=?
    i=172 i/2=86 buffer[i]=? buffer[i+1]=?
    i=174 i/2=87 buffer[i]=? buffer[i+1]=?
    i=176 i/2=88 buffer[i]=? buffer[i+1]=?
    i=178 i/2=89 buffer[i]=? buffer[i+1]=?
    i=180 i/2=90 buffer[i]=? buffer[i+1]=?
    i=182 i/2=91 buffer[i]=? buffer[i+1]=?
    i=184 i/2=92 buffer[i]=? buffer[i+1]=?
    i=186 i/2=93 buffer[i]=? buffer[i+1]=?
    i=188 i/2=94 buffer[i]=? buffer[i+1]=?
    i=190 i/2=95 buffer[i]=? buffer[i+1]=
I'm killing your brain like a poisonous mushroom????????????????????????????????????????????????
SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t////////////////////////////////////////////////////////////////

它循环太多次并且使用buffer数据乱码我似乎也得到了十六进制输入的ASCII版本。我无法看到这种情况如何发生,除了我对hex_char_to_raw的调用必须发生的事情。一些printf语句是我尝试调试代码以查看发生了什么,我已经打印了我传递给malloc的值以查看正在分配的内容以及某些中间值变量

令我感到困惑的是,如果我使用更简单的十六进制字符串,它将起作用。如果我用0x4d616e(&#34; Man&#34;)

运行它,这是输出
andrew@Andrews-MacBook-Air  Sat Jun 04 02:11:56  ~/Documents/Cryptopals Challenges/Set 1/Challenge 1 
     ->  ./test 0x4d616e
4D616E
6 3 6 8
    i=0 i/2=0 buffer[i]=4 buffer[i+1]=D
    i=2 i/2=1 buffer[i]=6 buffer[i+1]=1
    i=4 i/2=2 buffer[i]=6 buffer[i+1]=E
Man
TWFu

如果有人能指出我找到正在发生的事情的方向,我将非常感激。我确信它是一个小东西,但我一直在看这段代码,以至于我认为一双新眼睛可能会有用。

1 个答案:

答案 0 :(得分:-2)

Hans-Martin Mosner表示你的错,我补充了一些细节。 第一个错误:

char * buffer = malloc(sizeof(char)*(strlen(data)-2));

for (int i=2; i <= strlen(data); i++) {
    if (i != strlen(data))
        buffer[i-2] = data[i];
    else
        buffer[i-2] = '\0';
}
例如,&#34; 0x4d616e&#34; 长度是8,还不够&#39; \ 0&#39;。所以缓冲区的大小是6。 当你在

运行时
buffer[i-2] = '\0';

i-2 = 6,它超过了缓冲区的大小。

第二个错误:

for (int i=0; i < strlen(buffer); i=i+2) {
    printf("\ti=%u i/2=%u buffer[i]=%c buffer[i+1]=%c\n",i,i/2,buffer[i],buffer[i+1]);
    binary[i/2] = (hex_char_to_raw(buffer[i]) << 4) | (hex_char_to_raw(buffer[i+1]));
}

在此代码中,您不能添加&#39; \ 0&#39;在缓冲区结束;所以当你使用printf buffer时,会显示许多不可读的代码。 您应该在for(){...}之后添加binary[i/2] = '\0';。 当然,你应该在malloc二进制时添加1。