File: bug126147-x86.c

package info (click to toggle)
valgrind 1:3.14.0-3
  • links: PTS, VCS
  • area: main
  • in suites: buster, sid
  • size: 156,980 kB
  • sloc: ansic: 728,128; exp: 26,134; xml: 22,268; cpp: 7,638; asm: 7,312; makefile: 6,102; perl: 5,910; sh: 5,717
file content (206 lines) | stat: -rw-r--r-- 5,074 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "tests/asm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/* These fns taken from dietlibc-0.30 (is GPL v2'd) */

/*
  Copyright (C) 2002 Thomas M. Ogrisegg

  This is free software. You can redistribute and
  modify it under the terms of the GNU General Public
  Public License.

  strncpy.S
    i386 assembler implementation of strncpy(3)
*/
extern char *mystrncpy(char *dest, const char *src, size_t n);
asm(
".text\n"
"\n"
VG_SYM(mystrncpy) ":\n"
"	pushl %esi\n"
"	pushl %edi\n"
"	movl %esp, %ecx\n"
"	movl  0x0c(%ecx), %edi\n"
"	movl  0x10(%ecx), %esi\n"
"	movl  0x14(%ecx), %ecx\n"
"\n"
"	movl %edi, %edx\n"
"	cld\n"
"0:\n"
"	dec %ecx\n"
"	js 1f\n"
"	lodsb\n"
"	stosb\n"
"	or %al, %al\n"
"	jnz 0b\n"
"	repnz stosb\n"
"1:\n"
"	movl %edx, %eax\n"
"	popl %edi\n"
"	popl %esi\n"
"	ret\n"
"\n"
);


/*
   Copyright (C) 2002 Thomas M. Ogrisegg

   __ltostr.S -- convert an integer into a string

 %eax = dividend
 %ebx = divisor
 %ecx = size of output-buffer
 %edi = output-buffer
 %ebp = if uppercase is set, then %ebp is 'A'-10 else %ebp is 'a'-10

*/
extern int __ltostr(char *s, unsigned int size, unsigned long i, 
                             unsigned int base, int UpCase);
asm(
".text\n"
VG_SYM(__ltostr) ":\n"
"        pushl %esi\n"
"        pushl %edi              # destination\n"
"        pushl %ebp\n"
"        pushl %ebx\n"
"        movl %esp, %eax\n"
"        movl 0x14(%eax), %edi\n"
"        movl 0x18(%eax), %ecx   # size\n"
"        movl 0x20(%eax), %ebx   # divisor\n"
"        movl 0x1c(%eax), %eax   # dividend\n"
"        decl %ecx\n"
"        movl %ecx, %esi\n"
"        movl $55, %ebp          # 55 == char(A)-10\n"
"        xorl %edx, %edx         # must be 0 -- used by idiv\n"
"        cmpl $0x0, 36(%esp)     # check for uppercase\n"
"        jnz 0f\n"
"        addl $0x20, %ebp        # set lowercase\n"
"0:\n"
"        idiv %ebx, %eax\n"
"        cmpb $0x9, %dl\n"
"        jg 1f\n"
"        addb $48, %dl           # 48 == '0'\n"
"        jmp 2f\n"
"1:\n"
"        addl %ebp, %edx\n"
"2:\n"
"        movb %dl, (%edi, %ecx)\n"
"        xorl %edx, %edx\n"
"        decl %ecx\n"
"        jz 3f\n"
"        orl %eax, %eax\n"
"        jnz 0b\n"
"3:\n"
"        cld\n"
"        movl %esi, %ebx\n"
"        leal 1(%edi, %ecx), %esi\n"
"        subl %ebx, %ecx\n"
"        negl %ecx\n"
"        movl %ecx, %eax\n"
"        repnz movsb\n"
"        movb $0x0, (%edi)\n"
"        popl %ebx\n"
"        popl %ebp\n"
"        popl %edi\n"
"        popl %esi\n"
"        ret\n"
);

#define STREQ(a, b)     (strcmp((a), (b)) == 0)

const char *it = "<UNSET>";     /* Routine name for message routines. */
size_t errors = 0;

/* Complain if condition is not true.  */
static void
check (int thing, int number)
{
  if (!thing)
    {
      printf("%s flunked test %d\n", it, number);
      ++errors;
    }
}

/* Complain if first two args don't strcmp as equal.  */
static void
equal (const char *a, const char *b, int number)
{
  check(a != NULL && b != NULL && STREQ (a, b), number);
}

char one[50];
char two[50];
char *cp;

static void
test_strncpy (void)
{
  /* Testing is a bit different because of odd semantics.  */
  it = "strncpy";
  check (mystrncpy (one, "abc", 4) == one, 1);    /* Returned value. */
  equal (one, "abc", 2);                        /* Did the copy go right? */

  (void) strcpy (one, "abcdefgh");
  (void) mystrncpy (one, "xyz", 2);
  equal (one, "xycdefgh", 3);                   /* Copy cut by count. */

  (void) strcpy (one, "abcdefgh");
  (void) mystrncpy (one, "xyz", 3);               /* Copy cut just before NUL. */
  equal (one, "xyzdefgh", 4);

  (void) strcpy (one, "abcdefgh");
  (void) mystrncpy (one, "xyz", 4);               /* Copy just includes NUL. */
  equal (one, "xyz", 5);
  equal (one+4, "efgh", 6);                     /* Wrote too much? */

  (void) strcpy (one, "abcdefgh");
  (void) mystrncpy (one, "xyz", 5);               /* Copy includes padding. */
  equal (one, "xyz", 7);
  equal (one+4, "", 8);
  equal (one+5, "fgh", 9);

  (void) strcpy (one, "abc");
  (void) mystrncpy (one, "xyz", 0);               /* Zero-length copy. */
  equal (one, "abc", 10);

  (void) mystrncpy (one, "", 2);          /* Zero-length source. */
  equal (one, "", 11);
  equal (one+1, "", 12);
  equal (one+2, "c", 13);

  (void) strcpy (one, "hi there");
  (void) mystrncpy (two, one, 9);
  equal (two, "hi there", 14);          /* Just paranoia. */
  equal (one, "hi there", 15);          /* Stomped on source? */
}


int main ( void )
{
  char buf[1024];

  /* test strncpy, hence repnz stosb */
  test_strncpy();
    if (errors == 0)
    {
      printf("No errors.\n");
    }
  else
    {
      printf("%d errors.\n", (int)errors);
    }

    /* test __ltostr, hence repnz stosb */ 
  assert(__ltostr(buf,10,1723,10,0)==4); assert(!strcmp(buf,"1723"));
  assert(__ltostr(buf,3,1723,10,0)==2); assert(!strcmp(buf,"23"));
  assert(__ltostr(buf,2,0x1234,16,0)==1); assert(!strcmp(buf,"4"));
  assert(__ltostr(buf,3,0xFEFE,16,1)==2); assert(!strcmp(buf,"FE"));

 return 0;
}